From 397f345027fa7c3f5899c018b157a595225c8c4f Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Mon, 22 Dec 2025 23:24:29 +0100 Subject: [PATCH 1/8] Create Cargo workspace foundation for db/cli crate separation Initial workspace setup to extract database layer into a separate crate. This is the first step in a multi-ticket refactoring to improve modularity. Changes: - Convert root Cargo.toml to workspace manifest - Create db/ crate directory with minimal lib.rs stub - Create cli/ crate directory with Cargo.toml and main.rs stub - Move CLI dependencies to cli/Cargo.toml - Move db dependencies (cozo, thiserror) to db/Cargo.toml - Add db as path dependency in cli crate The original src/ directory is preserved for incremental migration in subsequent tickets. Relates to ticket: scratch/tickets/01-workspace-foundation.md --- Cargo.lock | 13 +++++++++++-- Cargo.toml | 25 +++++-------------------- cli/Cargo.toml | 20 ++++++++++++++++++++ cli/src/main.rs | 5 +++++ db/Cargo.toml | 10 ++++++++++ db/src/lib.rs | 1 + 6 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 cli/Cargo.toml create mode 100644 cli/src/main.rs create mode 100644 db/Cargo.toml create mode 100644 db/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 8396dc1..3dbc92f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,7 @@ name = "code_search" version = "0.1.0" dependencies = [ "clap", - "cozo", + "db", "enum_dispatch", "home", "include_dir", @@ -368,7 +368,6 @@ dependencies = [ "serde_json", "serial_test", "tempfile", - "thiserror", "toon", ] @@ -550,6 +549,16 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "db" +version = "0.1.0" +dependencies = [ + "cozo", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "delegate" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 294354a..1d6d68f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,7 @@ -[package] -name = "code_search" +[workspace] +resolver = "2" +members = ["db", "cli"] + +[workspace.package] version = "0.1.0" edition = "2024" - -[dependencies] -clap = { version = "4", features = ["derive"] } -cozo = { version = "0.7.6", default-features = false, features = ["compact", "storage-sqlite"] } -enum_dispatch = "0.3" -thiserror = "1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -toon = "0.1" -regex = "1" -include_dir = "0.7" -home = "0.5.12" - -[dev-dependencies] -tempfile = "3" -rstest = "0.23" -serial_test = "3.2.0" - diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 0000000..6821720 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "code_search" +version.workspace = true +edition.workspace = true + +[dependencies] +db = { path = "../db" } +clap = { version = "4", features = ["derive"] } +enum_dispatch = "0.3" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +toon = "0.1" +regex = "1" +include_dir = "0.7" +home = "0.5.12" + +[dev-dependencies] +tempfile = "3" +rstest = "0.23" +serial_test = "3.2.0" diff --git a/cli/src/main.rs b/cli/src/main.rs new file mode 100644 index 0000000..6b83fa5 --- /dev/null +++ b/cli/src/main.rs @@ -0,0 +1,5 @@ +// CLI crate entry point +// Modules will be migrated here in subsequent refactoring tickets +fn main() { + println!("Code search CLI - workspace refactoring in progress"); +} diff --git a/db/Cargo.toml b/db/Cargo.toml new file mode 100644 index 0000000..e089039 --- /dev/null +++ b/db/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "db" +version.workspace = true +edition.workspace = true + +[dependencies] +cozo = { version = "0.7.6", default-features = false, features = ["compact", "storage-sqlite"] } +thiserror = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" diff --git a/db/src/lib.rs b/db/src/lib.rs new file mode 100644 index 0000000..4bac6de --- /dev/null +++ b/db/src/lib.rs @@ -0,0 +1 @@ +// Database crate for code_search From bdd6bbd5d49e1947d715455cc7e5eed871ee30e3 Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Mon, 22 Dec 2025 23:34:44 +0100 Subject: [PATCH 2/8] Move types and db utilities to db crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ticket 2 of 8 - Build database crate core foundation. Changes: - Update db/Cargo.toml with all dependencies (cozo, serde, thiserror, regex, include_dir) - Copy types module to db/src/types/ (call.rs, results.rs, trace.rs, mod.rs) - Copy db.rs to db/src/db.rs (505 lines with DB utilities) - Create db/src/lib.rs with public module declarations and re-exports - Add test-utils feature flag for conditional test exports The db crate now has: - Database connection management (open_db, open_mem_db) - Query execution utilities (run_query, run_query_no_params) - Type-safe extraction helpers (extract_string, extract_i64, etc.) - CallRowLayout for structured call data extraction - All core types (Call, FunctionRef, ModuleGroup, TraceResult, etc.) Verification: - cargo build -p db: ✅ compiles successfully - cargo test -p db: ✅ all 24 tests pass Original src/ directory preserved for continued migration. Relates to ticket: scratch/tickets/02-db-crate-core.md --- db/Cargo.toml | 12 +- db/src/db.rs | 504 ++++++++++++++++++++++++++++++++++++++++ db/src/lib.rs | 17 +- db/src/types/call.rs | 332 ++++++++++++++++++++++++++ db/src/types/mod.rs | 16 ++ db/src/types/results.rs | 38 +++ db/src/types/trace.rs | 53 +++++ 7 files changed, 969 insertions(+), 3 deletions(-) create mode 100644 db/src/db.rs create mode 100644 db/src/types/call.rs create mode 100644 db/src/types/mod.rs create mode 100644 db/src/types/results.rs create mode 100644 db/src/types/trace.rs diff --git a/db/Cargo.toml b/db/Cargo.toml index e089039..442e597 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -5,6 +5,14 @@ edition.workspace = true [dependencies] cozo = { version = "0.7.6", default-features = false, features = ["compact", "storage-sqlite"] } -thiserror = "1.0" serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" +thiserror = "1.0" +regex = "1" +include_dir = "0.7" + +[dev-dependencies] +rstest = "0.23" +tempfile = "3" + +[features] +test-utils = [] diff --git a/db/src/db.rs b/db/src/db.rs new file mode 100644 index 0000000..e74370d --- /dev/null +++ b/db/src/db.rs @@ -0,0 +1,504 @@ +//! Database connection and query utilities for CozoDB. +//! +//! This module provides the database abstraction layer for the CLI tool: +//! - Connection management (SQLite-backed or in-memory for tests) +//! - Query execution with parameter binding +//! - Result row extraction with type-safe helpers +//! +//! # Architecture +//! +//! CozoDB is a Datalog database that stores call graph data in relations. +//! Queries are written in CozoScript (a Datalog variant) and return `NamedRows` +//! containing `DataValue` cells that must be extracted into Rust types. +//! +//! # Type Decisions +//! +//! **Why `i64` for arity/line numbers instead of `u32`?** +//! CozoDB returns all integers as `Num::Int(i64)`. Using `i64` throughout avoids +//! lossy conversions and potential panics. The semantic constraint (arity >= 0) +//! is enforced by the data source (Elixir AST), not runtime checks. +//! +//! **Why `CallRowLayout` with indices instead of serde deserialization?** +//! CozoDB returns rows as `Vec`, not JSON objects. The `CallRowLayout` +//! struct documents column positions for each query type, centralizing the +//! mapping in two factory methods rather than scattering magic numbers. +//! +//! **Why bare `String` for module/function names instead of newtypes?** +//! For a CLI tool, the complexity of newtype wrappers (`.0` access, `Into` impls, +//! derive macro limitations) outweighs the type safety benefit. Field names +//! (`module`, `name`) are sufficiently clear. + +use std::collections::{BTreeMap, HashMap}; +use std::error::Error; +use std::path::Path; +use std::rc::Rc; + +use cozo::{DataValue, DbInstance, NamedRows, ScriptMutability}; +use thiserror::Error; + +use crate::types::{Call, FunctionRef}; + +#[derive(Error, Debug)] +pub enum DbError { + #[error("Failed to open database '{path}': {message}")] + OpenFailed { path: String, message: String }, + + #[error("Query failed: {message}")] + QueryFailed { message: String }, + + #[error("Missing column '{name}' in query result")] + MissingColumn { name: String }, +} + +pub type Params = BTreeMap; + +pub fn open_db(path: &Path) -> Result> { + DbInstance::new("sqlite", path, "").map_err(|e| { + Box::new(DbError::OpenFailed { + path: path.display().to_string(), + message: format!("{:?}", e), + }) as Box + }) +} + +/// Create an in-memory database instance. +/// +/// Used for tests to avoid disk I/O and temp file management. +#[cfg(test)] +pub fn open_mem_db() -> DbInstance { + DbInstance::new("mem", "", "").expect("Failed to create in-memory DB") +} + +/// Run a mutable query (insert, delete, create, etc.) +pub fn run_query( + db: &DbInstance, + script: &str, + params: Params, +) -> Result> { + db.run_script(script, params, ScriptMutability::Mutable) + .map_err(|e| { + Box::new(DbError::QueryFailed { + message: format!("{:?}", e), + }) as Box + }) +} + +/// Run a mutable query with no parameters +pub fn run_query_no_params(db: &DbInstance, script: &str) -> Result> { + run_query(db, script, Params::new()) +} + +/// Escape a string for use in CozoDB string literals. +/// +/// # Arguments +/// * `s` - The string to escape +/// * `quote_char` - The quote character to escape ('"' for double-quoted, '\'' for single-quoted) +pub fn escape_string_for_quote(s: &str, quote_char: char) -> String { + let mut result = String::with_capacity(s.len() * 2); + for c in s.chars() { + match c { + '\\' => result.push_str("\\\\"), + c if c == quote_char => { + result.push('\\'); + result.push(c); + } + '\n' => result.push_str("\\n"), + '\r' => result.push_str("\\r"), + '\t' => result.push_str("\\t"), + c if c.is_control() || c == '\0' => { + // Escape control characters as \uXXXX (JSON format) + result.push_str(&format!("\\u{:04x}", c as u32)); + } + c => result.push(c), + } + } + result +} + +/// Escape a string for use in CozoDB double-quoted string literals (JSON-compatible) +#[inline] +pub fn escape_string(s: &str) -> String { + escape_string_for_quote(s, '"') +} + +/// Escape a string for use in CozoDB single-quoted string literals. +/// Use this for strings that may contain double quotes or complex content. +#[inline] +pub fn escape_string_single(s: &str) -> String { + escape_string_for_quote(s, '\'') +} + +/// Try to create a relation, returning Ok(true) if created, Ok(false) if already exists +pub fn try_create_relation(db: &DbInstance, script: &str) -> Result> { + match run_query_no_params(db, script) { + Ok(_) => Ok(true), + Err(e) => { + let err_str = e.to_string(); + if err_str.contains("AlreadyExists") || err_str.contains("stored_relation_conflict") { + Ok(false) + } else { + Err(e) + } + } + } +} + +// DataValue extraction helpers + +use cozo::Num; + +/// Extract a String from a DataValue, returning None if not a string +pub fn extract_string(value: &DataValue) -> Option { + match value { + DataValue::Str(s) => Some(s.to_string()), + _ => None, + } +} + +/// Extract an i64 from a DataValue, returning the default if not a number +pub fn extract_i64(value: &DataValue, default: i64) -> i64 { + match value { + DataValue::Num(Num::Int(i)) => *i, + DataValue::Num(Num::Float(f)) => *f as i64, + _ => default, + } +} + +/// Extract a String from a DataValue, returning the default if not a string +pub fn extract_string_or(value: &DataValue, default: &str) -> String { + match value { + DataValue::Str(s) => s.to_string(), + _ => default.to_string(), + } +} + +/// Extract a bool from a DataValue, returning the default if not a bool +pub fn extract_bool(value: &DataValue, default: bool) -> bool { + match value { + DataValue::Bool(b) => *b, + _ => default, + } +} + +/// Extract an f64 from a DataValue, returning the default if not a number +pub fn extract_f64(value: &DataValue, default: f64) -> f64 { + match value { + DataValue::Num(Num::Int(i)) => *i as f64, + DataValue::Num(Num::Float(f)) => *f, + _ => default, + } +} + +/// Layout descriptor for extracting call data from query result rows +#[derive(Debug)] +pub struct CallRowLayout { + pub caller_module_idx: usize, + pub caller_name_idx: usize, + pub caller_arity_idx: usize, + pub caller_kind_idx: usize, + pub caller_start_line_idx: usize, + pub caller_end_line_idx: usize, + pub callee_module_idx: usize, + pub callee_name_idx: usize, + pub callee_arity_idx: usize, + pub file_idx: usize, + pub line_idx: usize, + pub call_type_idx: Option, +} + +impl CallRowLayout { + /// Build layout dynamically from query result headers. + /// + /// This looks up column positions by name, making queries resilient to + /// column reordering. Returns error if any required column is missing. + /// + /// Expected column names (from CozoScript queries): + /// - caller_module, caller_name, caller_arity, caller_kind + /// - caller_start_line, caller_end_line + /// - callee_module, callee_function, callee_arity + /// - file, call_line + /// - call_type (optional) + pub fn from_headers(headers: &[String]) -> Result { + // Build lookup map once: O(m) where m = number of headers + let header_map: HashMap<&str, usize> = headers + .iter() + .enumerate() + .map(|(i, h)| (h.as_str(), i)) + .collect(); + + // Helper for required columns: O(1) each + let find = |name: &str| -> Result { + header_map + .get(name) + .copied() + .ok_or_else(|| DbError::MissingColumn { + name: name.to_string(), + }) + }; + + Ok(Self { + caller_module_idx: find("caller_module")?, + caller_name_idx: find("caller_name")?, + caller_arity_idx: find("caller_arity")?, + caller_kind_idx: find("caller_kind")?, + caller_start_line_idx: find("caller_start_line")?, + caller_end_line_idx: find("caller_end_line")?, + callee_module_idx: find("callee_module")?, + callee_name_idx: find("callee_function")?, + callee_arity_idx: find("callee_arity")?, + file_idx: find("file")?, + line_idx: find("call_line")?, + call_type_idx: header_map.get("call_type").copied(), + }) + } +} + +/// Extract call data from a query result row +/// +/// Returns Option if all required fields are present. Uses early return +/// (None) if any required string field cannot be extracted. +pub fn extract_call_from_row(row: &[DataValue], layout: &CallRowLayout) -> Option { + // Extract caller information + let Some(caller_module) = extract_string(&row[layout.caller_module_idx]) else { return None }; + let Some(caller_name) = extract_string(&row[layout.caller_name_idx]) else { return None }; + let caller_arity = extract_i64(&row[layout.caller_arity_idx], 0); + let caller_kind = extract_string_or(&row[layout.caller_kind_idx], ""); + let caller_start_line = extract_i64(&row[layout.caller_start_line_idx], 0); + let caller_end_line = extract_i64(&row[layout.caller_end_line_idx], 0); + + // Extract callee information + let Some(callee_module) = extract_string(&row[layout.callee_module_idx]) else { return None }; + let Some(callee_name) = extract_string(&row[layout.callee_name_idx]) else { return None }; + let callee_arity = extract_i64(&row[layout.callee_arity_idx], 0); + + // Extract file and line + let Some(file) = extract_string(&row[layout.file_idx]) else { return None }; + let line = extract_i64(&row[layout.line_idx], 0); + + // Extract optional call_type + let call_type = layout.call_type_idx.and_then(|idx| { + if idx < row.len() { + Some(extract_string_or(&row[idx], "remote")) + } else { + None + } + }); + + // Create FunctionRef objects with Rc to reduce memory allocations + let caller = FunctionRef::with_definition( + Rc::from(caller_module.into_boxed_str()), + Rc::from(caller_name.into_boxed_str()), + caller_arity, + Rc::from(caller_kind.into_boxed_str()), + Rc::from(file.into_boxed_str()), + caller_start_line, + caller_end_line, + ); + + let callee = FunctionRef::new( + Rc::from(callee_module.into_boxed_str()), + Rc::from(callee_name.into_boxed_str()), + callee_arity, + ); + + // Return Call + Some(Call { + caller, + callee, + line, + call_type, + depth: None, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use cozo::Num; + use rstest::rstest; + + #[rstest] + fn test_extract_string_from_str() { + let value = DataValue::Str("hello".into()); + assert_eq!(extract_string(&value), Some("hello".to_string())); + } + + #[rstest] + fn test_extract_string_from_non_str() { + let value = DataValue::Num(Num::Int(42)); + assert_eq!(extract_string(&value), None); + } + + #[rstest] + fn test_extract_i64_from_int() { + let value = DataValue::Num(Num::Int(42)); + assert_eq!(extract_i64(&value, 0), 42); + } + + #[rstest] + fn test_extract_i64_from_float() { + let value = DataValue::Num(Num::Float(42.7)); + assert_eq!(extract_i64(&value, 0), 42); + } + + #[rstest] + fn test_extract_i64_from_non_num() { + let value = DataValue::Str("not a number".into()); + assert_eq!(extract_i64(&value, -1), -1); + } + + #[rstest] + fn test_extract_string_or_from_str() { + let value = DataValue::Str("hello".into()); + assert_eq!(extract_string_or(&value, "default"), "hello"); + } + + #[rstest] + fn test_extract_string_or_from_non_str() { + let value = DataValue::Num(Num::Int(42)); + assert_eq!(extract_string_or(&value, "default"), "default"); + } + + #[rstest] + fn test_escape_string_basic() { + assert_eq!(escape_string("hello"), "hello"); + } + + #[rstest] + fn test_escape_string_with_quotes() { + assert_eq!(escape_string(r#"say "hello""#), r#"say \"hello\""#); + } + + #[rstest] + fn test_escape_string_with_backslash() { + assert_eq!(escape_string(r"path\to\file"), r"path\\to\\file"); + } + + #[rstest] + fn test_extract_bool_from_bool() { + let value = DataValue::Bool(true); + assert_eq!(extract_bool(&value, false), true); + } + + #[rstest] + fn test_extract_bool_from_non_bool() { + let value = DataValue::Str("true".into()); + assert_eq!(extract_bool(&value, false), false); + } + + // CallRowLayout::from_headers tests + + fn standard_headers() -> Vec { + vec![ + "caller_module", + "caller_name", + "caller_arity", + "caller_kind", + "caller_start_line", + "caller_end_line", + "callee_module", + "callee_function", + "callee_arity", + "file", + "call_line", + ] + .into_iter() + .map(String::from) + .collect() + } + + #[rstest] + fn test_from_headers_all_required_columns() { + let headers = standard_headers(); + let layout = CallRowLayout::from_headers(&headers).unwrap(); + + assert_eq!(layout.caller_module_idx, 0); + assert_eq!(layout.caller_name_idx, 1); + assert_eq!(layout.caller_arity_idx, 2); + assert_eq!(layout.caller_kind_idx, 3); + assert_eq!(layout.caller_start_line_idx, 4); + assert_eq!(layout.caller_end_line_idx, 5); + assert_eq!(layout.callee_module_idx, 6); + assert_eq!(layout.callee_name_idx, 7); + assert_eq!(layout.callee_arity_idx, 8); + assert_eq!(layout.file_idx, 9); + assert_eq!(layout.line_idx, 10); + assert_eq!(layout.call_type_idx, None); + } + + #[rstest] + fn test_from_headers_with_optional_call_type() { + let mut headers = standard_headers(); + headers.push("call_type".to_string()); + + let layout = CallRowLayout::from_headers(&headers).unwrap(); + assert_eq!(layout.call_type_idx, Some(11)); + } + + #[rstest] + fn test_from_headers_different_column_order() { + // Columns in different order - the key benefit of dynamic lookup + let headers: Vec = vec![ + "file", + "callee_module", + "caller_module", + "call_line", + "caller_name", + "callee_function", + "caller_arity", + "callee_arity", + "caller_kind", + "caller_start_line", + "caller_end_line", + "call_type", + ] + .into_iter() + .map(String::from) + .collect(); + + let layout = CallRowLayout::from_headers(&headers).unwrap(); + + assert_eq!(layout.file_idx, 0); + assert_eq!(layout.callee_module_idx, 1); + assert_eq!(layout.caller_module_idx, 2); + assert_eq!(layout.line_idx, 3); + assert_eq!(layout.caller_name_idx, 4); + assert_eq!(layout.callee_name_idx, 5); + assert_eq!(layout.caller_arity_idx, 6); + assert_eq!(layout.callee_arity_idx, 7); + assert_eq!(layout.caller_kind_idx, 8); + assert_eq!(layout.caller_start_line_idx, 9); + assert_eq!(layout.caller_end_line_idx, 10); + assert_eq!(layout.call_type_idx, Some(11)); + } + + #[rstest] + fn test_from_headers_missing_required_column() { + let headers: Vec = vec![ + "caller_module", + "caller_name", + // missing caller_arity + "caller_kind", + ] + .into_iter() + .map(String::from) + .collect(); + + let result = CallRowLayout::from_headers(&headers); + assert!(result.is_err()); + + let err = result.unwrap_err(); + assert!(matches!(err, DbError::MissingColumn { name } if name == "caller_arity")); + } + + #[rstest] + fn test_from_headers_error_message() { + let headers: Vec = vec!["caller_module".to_string()]; + + let err = CallRowLayout::from_headers(&headers).unwrap_err(); + assert_eq!( + err.to_string(), + "Missing column 'caller_name' in query result" + ); + } +} diff --git a/db/src/lib.rs b/db/src/lib.rs index 4bac6de..b242760 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -1 +1,16 @@ -// Database crate for code_search +//! Database layer for code search - CozoDB queries and call graph data structures + +pub mod db; +pub mod types; + +// Re-export commonly used items +pub use db::{open_db, run_query, run_query_no_params, DbError, Params}; + +#[cfg(test)] +pub use db::open_mem_db; + +pub use types::{ + Call, FunctionRef, ModuleGroup, ModuleGroupResult, + ModuleCollectionResult, TraceResult, TraceEntry, + TraceDirection, SharedStr +}; diff --git a/db/src/types/call.rs b/db/src/types/call.rs new file mode 100644 index 0000000..829c100 --- /dev/null +++ b/db/src/types/call.rs @@ -0,0 +1,332 @@ +//! Core types for representing function calls. + +use std::rc::Rc; +use serde::{Serialize, Serializer}; + +/// A function reference with optional definition location and type information. +/// Queries populate only the fields they need - optional fields are skipped during serialization. +/// Uses Rc for module and function names to reduce memory allocations when +/// the same names appear multiple times (which is typical in call graphs). +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FunctionRef { + pub module: Rc, + pub name: Rc, + pub arity: i64, + pub kind: Option>, + pub file: Option>, + pub start_line: Option, + pub end_line: Option, + pub args: Option>, + pub return_type: Option>, +} + +impl Serialize for FunctionRef { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + use serde::ser::SerializeStruct; + let mut state = serializer.serialize_struct("FunctionRef", 9)?; + state.serialize_field("module", self.module.as_ref())?; + state.serialize_field("name", self.name.as_ref())?; + state.serialize_field("arity", &self.arity)?; + if self.kind.is_some() { + state.serialize_field("kind", &self.kind.as_deref())?; + } + if self.file.is_some() { + state.serialize_field("file", &self.file.as_deref())?; + } + if self.start_line.is_some() { + state.serialize_field("start_line", &self.start_line)?; + } + if self.end_line.is_some() { + state.serialize_field("end_line", &self.end_line)?; + } + if self.args.is_some() { + state.serialize_field("args", &self.args.as_deref())?; + } + if self.return_type.is_some() { + state.serialize_field("return_type", &self.return_type.as_deref())?; + } + state.end() + } +} + +impl FunctionRef { + /// Create a minimal function reference (module, name, arity only). + pub fn new(module: impl Into>, name: impl Into>, arity: i64) -> Self { + Self { + module: module.into(), + name: name.into(), + arity, + kind: None, + file: None, + start_line: None, + end_line: None, + args: None, + return_type: None, + } + } + + /// Create a function reference with full definition info. + pub fn with_definition( + module: impl Into>, + name: impl Into>, + arity: i64, + kind: impl Into>, + file: impl Into>, + start_line: i64, + end_line: i64, + ) -> Self { + Self { + module: module.into(), + name: name.into(), + arity, + kind: Some(kind.into()), + file: Some(file.into()), + start_line: Some(start_line), + end_line: Some(end_line), + args: None, + return_type: None, + } + } + + /// Create a function reference with type information. + pub fn with_types( + module: impl Into>, + name: impl Into>, + arity: i64, + kind: impl Into>, + file: impl Into>, + start_line: i64, + end_line: i64, + args: impl Into>, + return_type: impl Into>, + ) -> Self { + Self { + module: module.into(), + name: name.into(), + arity, + kind: Some(kind.into()), + file: Some(file.into()), + start_line: Some(start_line), + end_line: Some(end_line), + args: Some(args.into()), + return_type: Some(return_type.into()), + } + } + + /// Format as "name/arity" or "Module.name/arity" if module differs from context. + pub fn format_name(&self, context_module: Option<&str>) -> String { + if context_module == Some(self.module.as_ref()) { + format!("{}/{}", self.name, self.arity) + } else { + format!("{}.{}/{}", self.module, self.name, self.arity) + } + } + + /// Format location as "L42:50" or "file.ex:L42:50". + /// Returns None if no location info available. + pub fn format_location(&self, context_file: Option<&str>) -> Option { + let (start, end) = match (self.start_line, self.end_line) { + (Some(s), Some(e)) => (s, e), + _ => return None, + }; + + let file = self.file.as_deref()?; + let filename = file.rsplit('/').next().unwrap_or(file); + let context_filename = context_file + .map(|f| f.rsplit('/').next().unwrap_or(f)); + + if context_filename == Some(filename) { + Some(format!("L{}:{}", start, end)) + } else { + Some(format!("{}:L{}:{}", filename, start, end)) + } + } + + /// Format kind as "[def]" or empty string if no kind. + pub fn format_kind(&self) -> String { + self.kind + .as_ref() + .filter(|k| !k.is_empty()) + .map(|k| format!(" [{}]", k)) + .unwrap_or_default() + } +} + +/// A directed call relationship. +#[derive(Debug, Clone, Serialize)] +pub struct Call { + pub caller: FunctionRef, + pub callee: FunctionRef, + pub line: i64, + #[serde(skip_serializing_if = "Option::is_none")] + pub call_type: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub depth: Option, +} + +impl Call { + /// Check if this is a struct construction call (e.g., %MyStruct{}). + pub fn is_struct_call(&self) -> bool { + self.callee.name.as_ref() == "%" + } + + /// Format as outgoing call: "→ @ L37 name/arity [kind] (location)" + pub fn format_outgoing(&self, context_module: &str, context_file: &str) -> String { + let name = self.callee.format_name(Some(context_module)); + let kind = self.callee.format_kind(); + let location = self + .callee + .format_location(Some(context_file)) + .map(|loc| format!(" ({})", loc)) + .unwrap_or_default(); + + format!("→ @ L{} {}{}{}", self.line, name, kind, location) + } + + /// Format as incoming call: "← @ L37 name/arity [kind] (location)" + pub fn format_incoming(&self, context_module: &str, context_file: &str) -> String { + let name = self.caller.format_name(Some(context_module)); + let kind = self.caller.format_kind(); + let location = self + .caller + .format_location(Some(context_file)) + .map(|loc| format!(" ({})", loc)) + .unwrap_or_default(); + + format!("← @ L{} {}{}{}", self.line, name, kind, location) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_function_ref_format_name_same_module() { + let func = FunctionRef::new("MyModule", "my_func", 2); + assert_eq!(func.format_name(Some("MyModule")), "my_func/2"); + } + + #[test] + fn test_function_ref_format_name_different_module() { + let func = FunctionRef::new("OtherModule", "other_func", 1); + assert_eq!( + func.format_name(Some("MyModule")), + "OtherModule.other_func/1" + ); + } + + #[test] + fn test_function_ref_format_location_same_file() { + let func = FunctionRef::with_definition( + "MyModule", + "my_func", + 2, + "def", + "/path/to/my_module.ex", + 10, + 20, + ); + assert_eq!( + func.format_location(Some("/other/path/my_module.ex")), + Some("L10:20".to_string()) + ); + } + + #[test] + fn test_function_ref_format_location_different_file() { + let func = FunctionRef::with_definition( + "MyModule", + "my_func", + 2, + "def", + "/path/to/my_module.ex", + 10, + 20, + ); + assert_eq!( + func.format_location(Some("/path/to/other.ex")), + Some("my_module.ex:L10:20".to_string()) + ); + } + + #[test] + fn test_call_format_outgoing() { + let call = Call { + caller: FunctionRef::with_definition( + "MyModule", + "caller_func", + 1, + "def", + "/path/to/my_module.ex", + 10, + 30, + ), + callee: FunctionRef::with_definition( + "MyModule", + "callee_func", + 2, + "defp", + "/path/to/my_module.ex", + 40, + 50, + ), + line: 25, + call_type: None, + depth: None, + }; + + assert_eq!( + call.format_outgoing("MyModule", "/path/to/my_module.ex"), + "→ @ L25 callee_func/2 [defp] (L40:50)" + ); + } + + #[test] + fn test_call_format_outgoing_different_module() { + let call = Call { + caller: FunctionRef::new("MyModule", "caller_func", 1), + callee: FunctionRef::with_definition( + "OtherModule", + "other_func", + 0, + "def", + "/path/to/other.ex", + 5, + 15, + ), + line: 12, + call_type: None, + depth: None, + }; + + assert_eq!( + call.format_outgoing("MyModule", "/path/to/my_module.ex"), + "→ @ L12 OtherModule.other_func/0 [def] (other.ex:L5:15)" + ); + } + + #[test] + fn test_is_struct_call() { + let struct_call = Call { + caller: FunctionRef::new("MyModule", "func", 1), + callee: FunctionRef::new("MyStruct", "%", 2), + line: 10, + call_type: None, + depth: None, + }; + assert!(struct_call.is_struct_call()); + + let normal_call = Call { + caller: FunctionRef::new("MyModule", "func", 1), + callee: FunctionRef::new("OtherModule", "other", 0), + line: 10, + call_type: None, + depth: None, + }; + assert!(!normal_call.is_struct_call()); + } +} diff --git a/db/src/types/mod.rs b/db/src/types/mod.rs new file mode 100644 index 0000000..3fe761f --- /dev/null +++ b/db/src/types/mod.rs @@ -0,0 +1,16 @@ +//! Shared types for call graph data. + +use std::rc::Rc; + +mod call; +mod results; +mod trace; + +pub use call::{Call, FunctionRef}; +pub use results::{ModuleGroupResult, ModuleCollectionResult, ModuleGroup}; +pub use trace::{TraceDirection, TraceEntry, TraceResult}; + +/// Type alias for shared, reference-counted strings. +/// Used throughout FunctionRef and Call structures to reduce memory allocations +/// when the same module/function names appear multiple times. +pub type SharedStr = Rc; diff --git a/db/src/types/results.rs b/db/src/types/results.rs new file mode 100644 index 0000000..b070c46 --- /dev/null +++ b/db/src/types/results.rs @@ -0,0 +1,38 @@ +use serde::Serialize; + +/// Generic result structure for commands that group entries by module +/// Used by calls_from, calls_to, depends_on, depended_by +#[derive(Debug, Default, Serialize)] +pub struct ModuleGroupResult { + pub module_pattern: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub function_pattern: Option, + pub total_items: usize, + pub items: Vec>, +} + +/// Generic result structure for commands with module grouping and multiple filter options +/// Used by function, specs, types +#[derive(Debug, Default, Serialize)] +pub struct ModuleCollectionResult { + pub module_pattern: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub function_pattern: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub kind_filter: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub name_filter: Option, + pub total_items: usize, + pub items: Vec>, +} + +/// A module with a collection of generic entries +#[derive(Debug, Default, Serialize)] +pub struct ModuleGroup { + pub name: String, + #[serde(skip_serializing_if = "String::is_empty")] + pub file: String, + pub entries: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub function_count: Option, +} diff --git a/db/src/types/trace.rs b/db/src/types/trace.rs new file mode 100644 index 0000000..e971fc9 --- /dev/null +++ b/db/src/types/trace.rs @@ -0,0 +1,53 @@ +//! Unified types for trace and reverse-trace commands. + +use serde::Serialize; + +/// Direction of trace traversal +#[derive(Debug, Clone, Copy, Default, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum TraceDirection { + #[default] + Forward, + Backward, +} + +/// A single entry in the trace tree (flattened representation) +#[derive(Debug, Clone, Serialize)] +pub struct TraceEntry { + pub module: String, + pub function: String, + pub arity: i64, + pub kind: String, + pub start_line: i64, + pub end_line: i64, + pub file: String, + pub depth: i64, + pub line: i64, // Line where the call happens + #[serde(skip_serializing_if = "Option::is_none")] + pub parent_index: Option, // Index in entries list of parent +} + +/// Result of trace or reverse-trace command execution +#[derive(Debug, Default, Serialize)] +pub struct TraceResult { + pub module: String, + pub function: String, + pub max_depth: u32, + pub direction: TraceDirection, + pub total_items: usize, // total_calls or total_callers + pub entries: Vec, +} + +impl TraceResult { + /// Create an empty trace result + pub fn empty(module: String, function: String, max_depth: u32, direction: TraceDirection) -> Self { + Self { + module, + function, + max_depth, + direction, + total_items: 0, + entries: vec![], + } + } +} From 1340dac8d42c803115772b0c1c3b7bb5f489dc77 Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Mon, 22 Dec 2025 23:38:45 +0100 Subject: [PATCH 3/8] Extract query builders from utils.rs to db crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ticket 3 of 8 - Extract SQL-specific query builders. Changes: - Create db/src/query_builders.rs with ConditionBuilder and OptionalConditionBuilder - Extract SQL builders from src/utils.rs (lines 8-154) - Extract builder tests from src/utils.rs (lines 640-684) - Update db/src/lib.rs with query_builders module and re-exports The query builders provide: - ConditionBuilder: Builds SQL conditions for exact or regex matching - OptionalConditionBuilder: Builds optional SQL conditions with defaults All 7 builder tests passing: - test_condition_builder_exact_match - test_condition_builder_regex_match - test_condition_builder_with_leading_comma - test_optional_condition_builder_with_value - test_optional_condition_builder_without_value - test_optional_condition_builder_with_default - test_optional_condition_builder_with_leading_comma Verification: - cargo build -p db: ✅ compiles successfully - cargo test -p db query_builders: ✅ all 7 tests pass Next ticket will update 6 query files to import from this new module. Relates to ticket: scratch/tickets/03-query-builders.md --- db/src/lib.rs | 3 + db/src/query_builders.rs | 200 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 db/src/query_builders.rs diff --git a/db/src/lib.rs b/db/src/lib.rs index b242760..f7c5c26 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -2,6 +2,7 @@ pub mod db; pub mod types; +pub mod query_builders; // Re-export commonly used items pub use db::{open_db, run_query, run_query_no_params, DbError, Params}; @@ -14,3 +15,5 @@ pub use types::{ ModuleCollectionResult, TraceResult, TraceEntry, TraceDirection, SharedStr }; + +pub use query_builders::{ConditionBuilder, OptionalConditionBuilder}; diff --git a/db/src/query_builders.rs b/db/src/query_builders.rs new file mode 100644 index 0000000..0ecca67 --- /dev/null +++ b/db/src/query_builders.rs @@ -0,0 +1,200 @@ +//! Query condition builders for CozoScript + +/// Builds SQL WHERE clause conditions for query patterns (exact or regex matching) +/// +/// Handles the common pattern of building conditions that differ between exact and regex modes. +/// Supports different field prefixes and optional leading comma. +/// +/// # Examples +/// +/// ```ignore +/// let builder = ConditionBuilder::new("module", "module_pattern"); +/// let cond = builder.build(false); // "module == $module_pattern" +/// let cond = builder.build(true); // "regex_matches(module, $module_pattern)" +/// ``` +pub struct ConditionBuilder { + field_name: String, + param_name: String, + with_leading_comma: bool, +} + +impl ConditionBuilder { + /// Creates a new condition builder for a field with exact/regex matching + /// + /// # Arguments + /// * `field_name` - The SQL field name (e.g., "module", "caller_module") + /// * `param_name` - The parameter name (e.g., "module_pattern", "function_pattern") + pub fn new(field_name: &str, param_name: &str) -> Self { + Self { + field_name: field_name.to_string(), + param_name: param_name.to_string(), + with_leading_comma: false, + } + } + + /// Adds a leading comma to the condition (useful for mid-query conditions) + pub fn with_leading_comma(mut self) -> Self { + self.with_leading_comma = true; + self + } + + /// Builds the condition string based on use_regex flag + /// + /// When `use_regex` is true, uses `regex_matches()`. + /// When `use_regex` is false, uses exact matching with `==`. + /// + /// # Arguments + /// * `use_regex` - Whether to use regex matching + /// + /// # Returns + /// A condition string ready to be interpolated into a SQL query + pub fn build(&self, use_regex: bool) -> String { + let prefix = if self.with_leading_comma { ", " } else { "" }; + + if use_regex { + format!( + "{}regex_matches({}, ${})", + prefix, self.field_name, self.param_name + ) + } else { + format!("{}{} == ${}", prefix, self.field_name, self.param_name) + } + } +} + +/// Builder for optional SQL conditions (function, arity, etc.) +/// +/// Handles the pattern of generating conditions only when values are present. +/// For function-matching conditions, supports both exact and regex matching. +pub struct OptionalConditionBuilder { + field_name: String, + param_name: String, + with_leading_comma: bool, + when_none: Option, // Alternative condition when value is None + supports_regex: bool, // Whether to use regex_matches when value is present +} + +impl OptionalConditionBuilder { + /// Creates a new optional condition builder + /// + /// # Arguments + /// * `field_name` - The SQL field name + /// * `param_name` - The parameter name + pub fn new(field_name: &str, param_name: &str) -> Self { + Self { + field_name: field_name.to_string(), + param_name: param_name.to_string(), + with_leading_comma: false, + when_none: None, + supports_regex: false, + } + } + + /// Enables regex matching (uses regex_matches when value is present) + pub fn with_regex(mut self) -> Self { + self.supports_regex = true; + self + } + + /// Adds a leading comma + pub fn with_leading_comma(mut self) -> Self { + self.with_leading_comma = true; + self + } + + /// Sets an alternative condition when the value is None (e.g., "true" for no-op) + pub fn when_none(mut self, condition: &str) -> Self { + self.when_none = Some(condition.to_string()); + self + } + + /// Builds the condition string + /// + /// # Arguments + /// * `has_value` - Whether the optional value is present + /// * `use_regex` - Whether to use regex matching (only matters if supports_regex is true) + /// + /// # Returns + /// A condition string, or empty string if no value and no alternative + pub fn build_with_regex(&self, has_value: bool, use_regex: bool) -> String { + let prefix = if self.with_leading_comma { ", " } else { "" }; + + if has_value { + if self.supports_regex && use_regex { + format!( + "{}regex_matches({}, ${})", + prefix, self.field_name, self.param_name + ) + } else { + format!("{}{} == ${}", prefix, self.field_name, self.param_name) + } + } else { + self.when_none + .as_ref() + .map(|cond| format!("{}{}", prefix, cond)) + .unwrap_or_default() + } + } + + /// Builds the condition string (non-regex version, for backward compatibility) + /// + /// # Arguments + /// * `has_value` - Whether the optional value is present + /// + /// # Returns + /// A condition string, or empty string if no value and no alternative + pub fn build(&self, has_value: bool) -> String { + self.build_with_regex(has_value, false) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_condition_builder_exact_match() { + let builder = ConditionBuilder::new("module", "module_pattern"); + assert_eq!(builder.build(false), "module == $module_pattern"); + } + + #[test] + fn test_condition_builder_regex_match() { + let builder = ConditionBuilder::new("module", "module_pattern"); + assert_eq!(builder.build(true), "regex_matches(module, $module_pattern)"); + } + + #[test] + fn test_condition_builder_with_leading_comma() { + let builder = ConditionBuilder::new("module", "module_pattern").with_leading_comma(); + assert_eq!(builder.build(false), ", module == $module_pattern"); + assert_eq!(builder.build(true), ", regex_matches(module, $module_pattern)"); + } + + #[test] + fn test_optional_condition_builder_with_value() { + let builder = OptionalConditionBuilder::new("arity", "arity"); + assert_eq!(builder.build(true), "arity == $arity"); + } + + #[test] + fn test_optional_condition_builder_without_value() { + let builder = OptionalConditionBuilder::new("arity", "arity"); + assert_eq!(builder.build(false), ""); + } + + #[test] + fn test_optional_condition_builder_with_default() { + let builder = OptionalConditionBuilder::new("arity", "arity").when_none("true"); + assert_eq!(builder.build(false), "true"); + } + + #[test] + fn test_optional_condition_builder_with_leading_comma() { + let builder = OptionalConditionBuilder::new("arity", "arity") + .with_leading_comma() + .when_none("true"); + assert_eq!(builder.build(true), ", arity == $arity"); + assert_eq!(builder.build(false), ", true"); + } +} From f0d80058540000603f2c72ab011f194a45a57cac Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Mon, 22 Dec 2025 23:46:12 +0100 Subject: [PATCH 4/8] Move all 31 query modules to db crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ticket 4 of 8 - Move queries module. Changes: - Copy all 31 query files from src/queries/ to db/src/queries/ - Update 6 query files to import from query_builders instead of utils: - calls.rs, trace.rs, reverse_trace.rs, path.rs, function.rs, dependencies.rs - Update db/src/lib.rs to export queries module - Add clap dependency (required by hotspots.rs) - Add serde_json dev-dependency (required by import.rs tests) Query modules now in db crate: - Data import: import.rs, import_models.rs, schema.rs - Basic lookups: location.rs, function.rs, search.rs, file.rs - Call graph: calls.rs, calls_from.rs, calls_to.rs, trace.rs, reverse_trace.rs, path.rs - Dependencies: depends_on.rs, depended_by.rs, dependencies.rs - Code quality: unused.rs, hotspots.rs, duplicates.rs, complexity.rs, large_functions.rs, many_clauses.rs, cycles.rs, clusters.rs - Type system: specs.rs, types.rs, structs.rs, struct_usage.rs, accepts.rs, returns.rs Verification: - cargo build -p db: ✅ compiles successfully - cargo test -p db --lib: ✅ 37 tests pass - No import warnings The db crate is now fully functional with all query logic. Relates to ticket: scratch/tickets/04-move-queries.md --- db/Cargo.toml | 2 + db/src/lib.rs | 1 + db/src/queries/accepts.rs | 107 +++++ db/src/queries/calls.rs | 132 ++++++ db/src/queries/calls_from.rs | 30 ++ db/src/queries/calls_to.rs | 30 ++ db/src/queries/clusters.rs | 58 +++ db/src/queries/complexity.rs | 112 +++++ db/src/queries/cycles.rs | 93 ++++ db/src/queries/depended_by.rs | 26 ++ db/src/queries/dependencies.rs | 114 +++++ db/src/queries/depends_on.rs | 26 ++ db/src/queries/duplicates.rs | 106 +++++ db/src/queries/file.rs | 99 ++++ db/src/queries/function.rs | 93 ++++ db/src/queries/hotspots.rs | 292 ++++++++++++ db/src/queries/import.rs | 724 ++++++++++++++++++++++++++++++ db/src/queries/import_models.rs | 145 ++++++ db/src/queries/large_functions.rs | 103 +++++ db/src/queries/location.rs | 121 +++++ db/src/queries/many_clauses.rs | 105 +++++ db/src/queries/mod.rs | 81 ++++ db/src/queries/path.rs | 245 ++++++++++ db/src/queries/returns.rs | 104 +++++ db/src/queries/reverse_trace.rs | 140 ++++++ db/src/queries/schema.rs | 180 ++++++++ db/src/queries/search.rs | 117 +++++ db/src/queries/specs.rs | 127 ++++++ db/src/queries/struct_usage.rs | 107 +++++ db/src/queries/structs.rs | 124 +++++ db/src/queries/trace.rs | 133 ++++++ db/src/queries/types.rs | 121 +++++ db/src/queries/unused.rs | 135 ++++++ 33 files changed, 4133 insertions(+) create mode 100644 db/src/queries/accepts.rs create mode 100644 db/src/queries/calls.rs create mode 100644 db/src/queries/calls_from.rs create mode 100644 db/src/queries/calls_to.rs create mode 100644 db/src/queries/clusters.rs create mode 100644 db/src/queries/complexity.rs create mode 100644 db/src/queries/cycles.rs create mode 100644 db/src/queries/depended_by.rs create mode 100644 db/src/queries/dependencies.rs create mode 100644 db/src/queries/depends_on.rs create mode 100644 db/src/queries/duplicates.rs create mode 100644 db/src/queries/file.rs create mode 100644 db/src/queries/function.rs create mode 100644 db/src/queries/hotspots.rs create mode 100644 db/src/queries/import.rs create mode 100644 db/src/queries/import_models.rs create mode 100644 db/src/queries/large_functions.rs create mode 100644 db/src/queries/location.rs create mode 100644 db/src/queries/many_clauses.rs create mode 100644 db/src/queries/mod.rs create mode 100644 db/src/queries/path.rs create mode 100644 db/src/queries/returns.rs create mode 100644 db/src/queries/reverse_trace.rs create mode 100644 db/src/queries/schema.rs create mode 100644 db/src/queries/search.rs create mode 100644 db/src/queries/specs.rs create mode 100644 db/src/queries/struct_usage.rs create mode 100644 db/src/queries/structs.rs create mode 100644 db/src/queries/trace.rs create mode 100644 db/src/queries/types.rs create mode 100644 db/src/queries/unused.rs diff --git a/db/Cargo.toml b/db/Cargo.toml index 442e597..3129629 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -9,10 +9,12 @@ serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" regex = "1" include_dir = "0.7" +clap = { version = "4", features = ["derive"] } [dev-dependencies] rstest = "0.23" tempfile = "3" +serde_json = "1.0" [features] test-utils = [] diff --git a/db/src/lib.rs b/db/src/lib.rs index f7c5c26..733014f 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -3,6 +3,7 @@ pub mod db; pub mod types; pub mod query_builders; +pub mod queries; // Re-export commonly used items pub use db::{open_db, run_query, run_query_no_params, DbError, Params}; diff --git a/db/src/queries/accepts.rs b/db/src/queries/accepts.rs new file mode 100644 index 0000000..4ffcf01 --- /dev/null +++ b/db/src/queries/accepts.rs @@ -0,0 +1,107 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum AcceptsError { + #[error("Accepts query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function with its input type specification +#[derive(Debug, Clone, Serialize)] +pub struct AcceptsEntry { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub inputs_string: String, + pub return_string: String, + pub line: i64, +} + +pub fn find_accepts( + db: &cozo::DbInstance, + pattern: &str, + project: &str, + use_regex: bool, + module_pattern: Option<&str>, + limit: u32, +) -> Result, Box> { + // Build inputs string filter + let match_fn = if use_regex { + "regex_matches(inputs_string, $pattern)" + } else { + "str_includes(inputs_string, $pattern)" + }; + + // Build module filter + let module_filter = match module_pattern { + Some(_) if use_regex => "regex_matches(module, $module_pattern)", + Some(_) => "str_includes(module, $module_pattern)", + None => "true", + }; + + let script = format!( + r#" + ?[project, module, name, arity, inputs_string, return_string, line] := + *specs{{project, module, name, arity, inputs_string, return_string, line}}, + project == $project, + {match_fn}, + {module_filter} + + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("pattern".to_string(), DataValue::Str(pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + if let Some(mod_pat) = module_pattern { + params.insert( + "module_pattern".to_string(), + DataValue::Str(mod_pat.into()), + ); + } + + let rows = run_query(db, &script, params).map_err(|e| AcceptsError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 7 { + let Some(project) = extract_string(&row[0]) else { + continue; + }; + let Some(module) = extract_string(&row[1]) else { + continue; + }; + let Some(name) = extract_string(&row[2]) else { + continue; + }; + let arity = extract_i64(&row[3], 0); + let inputs_string = extract_string(&row[4]).unwrap_or_default(); + let return_string = extract_string(&row[5]).unwrap_or_default(); + let line = extract_i64(&row[6], 0); + + results.push(AcceptsEntry { + project, + module, + name, + arity, + inputs_string, + return_string, + line, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/calls.rs b/db/src/queries/calls.rs new file mode 100644 index 0000000..bb668cf --- /dev/null +++ b/db/src/queries/calls.rs @@ -0,0 +1,132 @@ +//! Unified call graph queries for finding function calls. +//! +//! This module provides a single query function that can find calls in either direction: +//! - `From`: Find all calls made BY the matched functions (outgoing calls) +//! - `To`: Find all calls made TO the matched functions (incoming calls) + +use std::error::Error; + +use cozo::DataValue; +use thiserror::Error; + +use crate::db::{extract_call_from_row, run_query, CallRowLayout, Params}; +use crate::types::Call; +use crate::query_builders::{ConditionBuilder, OptionalConditionBuilder}; + +#[derive(Error, Debug)] +pub enum CallsError { + #[error("Calls query failed: {message}")] + QueryFailed { message: String }, +} + +/// Direction of call graph traversal +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum CallDirection { + /// Find calls FROM the matched functions (what does this function call?) + From, + /// Find calls TO the matched functions (who calls this function?) + To, +} + +impl CallDirection { + /// Returns the field names to filter on based on direction + fn filter_fields(&self) -> (&'static str, &'static str, &'static str) { + match self { + CallDirection::From => ("caller_module", "caller_name", "caller_arity"), + CallDirection::To => ("callee_module", "callee_function", "callee_arity"), + } + } + + /// Returns the ORDER BY clause based on direction + fn order_clause(&self) -> &'static str { + match self { + CallDirection::From => { + "caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity" + } + CallDirection::To => { + "callee_module, callee_function, callee_arity, caller_module, caller_name, caller_arity" + } + } + } +} + +/// Find calls in the specified direction. +/// +/// - `From`: Returns all calls made by functions matching the pattern +/// - `To`: Returns all calls to functions matching the pattern +pub fn find_calls( + db: &cozo::DbInstance, + direction: CallDirection, + module_pattern: &str, + function_pattern: Option<&str>, + arity: Option, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + let (module_field, function_field, arity_field) = direction.filter_fields(); + let order_clause = direction.order_clause(); + + // Build conditions using the appropriate field names + let module_cond = + ConditionBuilder::new(module_field, "module_pattern").build(use_regex); + let function_cond = + OptionalConditionBuilder::new(function_field, "function_pattern") + .with_leading_comma() + .with_regex() + .build_with_regex(function_pattern.is_some(), use_regex); + let arity_cond = OptionalConditionBuilder::new(arity_field, "arity") + .with_leading_comma() + .build(arity.is_some()); + + let project_cond = ", project == $project"; + + // Join calls with function_locations to get caller's arity and line range + // Filter out struct calls (callee_function == '%') + let script = format!( + r#" + ?[project, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line, call_type] := + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line, call_type, caller_kind}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, start_line: caller_start_line, end_line: caller_end_line}}, + starts_with(caller_function, caller_name), + call_line >= caller_start_line, + call_line <= caller_end_line, + callee_function != '%', + {module_cond} + {function_cond} + {arity_cond} + {project_cond} + :order {order_clause} + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert( + "module_pattern".to_string(), + DataValue::Str(module_pattern.into()), + ); + if let Some(fn_pat) = function_pattern { + params.insert( + "function_pattern".to_string(), + DataValue::Str(fn_pat.into()), + ); + } + if let Some(a) = arity { + params.insert("arity".to_string(), DataValue::from(a)); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| CallsError::QueryFailed { + message: e.to_string(), + })?; + + let layout = CallRowLayout::from_headers(&rows.headers)?; + let results = rows + .rows + .iter() + .filter_map(|row| extract_call_from_row(row, &layout)) + .collect(); + + Ok(results) +} diff --git a/db/src/queries/calls_from.rs b/db/src/queries/calls_from.rs new file mode 100644 index 0000000..3248b95 --- /dev/null +++ b/db/src/queries/calls_from.rs @@ -0,0 +1,30 @@ +//! Find outgoing calls from functions. +//! +//! This is a convenience wrapper around [`super::calls::find_calls`] with +//! [`CallDirection::From`](super::calls::CallDirection::From). + +use std::error::Error; + +use super::calls::{find_calls, CallDirection}; +use crate::types::Call; + +pub fn find_calls_from( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: Option<&str>, + arity: Option, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + find_calls( + db, + CallDirection::From, + module_pattern, + function_pattern, + arity, + project, + use_regex, + limit, + ) +} diff --git a/db/src/queries/calls_to.rs b/db/src/queries/calls_to.rs new file mode 100644 index 0000000..fef5d98 --- /dev/null +++ b/db/src/queries/calls_to.rs @@ -0,0 +1,30 @@ +//! Find incoming calls to functions. +//! +//! This is a convenience wrapper around [`super::calls::find_calls`] with +//! [`CallDirection::To`](super::calls::CallDirection::To). + +use std::error::Error; + +use super::calls::{find_calls, CallDirection}; +use crate::types::Call; + +pub fn find_calls_to( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: Option<&str>, + arity: Option, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + find_calls( + db, + CallDirection::To, + module_pattern, + function_pattern, + arity, + project, + use_regex, + limit, + ) +} diff --git a/db/src/queries/clusters.rs b/db/src/queries/clusters.rs new file mode 100644 index 0000000..892503c --- /dev/null +++ b/db/src/queries/clusters.rs @@ -0,0 +1,58 @@ +//! Query to get all module calls for cluster analysis. +//! +//! Returns calls between different modules (no self-calls). +//! Clusters are computed in Rust by grouping modules by namespace. + +use std::error::Error; + +use cozo::DataValue; + +use crate::db::{run_query, Params}; + +/// Represents a call between two different modules +#[derive(Debug, Clone)] +pub struct ModuleCall { + pub caller_module: String, + pub callee_module: String, +} + +/// Get all inter-module calls (calls between different modules) +/// +/// Returns calls where caller_module != callee_module. +/// These are used to compute internal vs external connectivity per namespace cluster. +pub fn get_module_calls(db: &cozo::DbInstance, project: &str) -> Result, Box> { + let script = r#" + ?[caller_module, callee_module] := + *calls{project, caller_module, callee_module}, + project == $project, + caller_module != callee_module + "#; + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, script, params)?; + + let caller_idx = rows.headers.iter().position(|h| h == "caller_module") + .ok_or("Missing caller_module column")?; + let callee_idx = rows.headers.iter().position(|h| h == "callee_module") + .ok_or("Missing callee_module column")?; + + let results = rows + .rows + .iter() + .filter_map(|row| { + let caller = row.get(caller_idx).and_then(|v| v.get_str()); + let callee = row.get(callee_idx).and_then(|v| v.get_str()); + match (caller, callee) { + (Some(c), Some(m)) => Some(ModuleCall { + caller_module: c.to_string(), + callee_module: m.to_string(), + }), + _ => None, + } + }) + .collect(); + + Ok(results) +} diff --git a/db/src/queries/complexity.rs b/db/src/queries/complexity.rs new file mode 100644 index 0000000..672dd22 --- /dev/null +++ b/db/src/queries/complexity.rs @@ -0,0 +1,112 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum ComplexityError { + #[error("Complexity query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function with complexity metrics +#[derive(Debug, Clone, Serialize)] +pub struct ComplexityMetric { + pub module: String, + pub name: String, + pub arity: i64, + pub line: i64, + pub complexity: i64, + pub max_nesting_depth: i64, + pub start_line: i64, + pub end_line: i64, + pub lines: i64, + pub generated_by: String, +} + +pub fn find_complexity_metrics( + db: &cozo::DbInstance, + min_complexity: i64, + min_depth: i64, + module_pattern: Option<&str>, + project: &str, + use_regex: bool, + exclude_generated: bool, + limit: u32, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build optional generated filter + let generated_filter = if exclude_generated { + ", generated_by == \"\"".to_string() + } else { + String::new() + }; + + let script = format!( + r#" + ?[module, name, arity, line, complexity, max_nesting_depth, start_line, end_line, lines, generated_by] := + *function_locations{{project, module, name, arity, line, complexity, max_nesting_depth, start_line, end_line, generated_by}}, + project == $project, + complexity >= $min_complexity, + max_nesting_depth >= $min_depth, + lines = end_line - start_line + 1 + {module_filter} + {generated_filter} + + :order -complexity, module, name + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert("min_complexity".to_string(), DataValue::from(min_complexity)); + params.insert("min_depth".to_string(), DataValue::from(min_depth)); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| ComplexityError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 10 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let arity = extract_i64(&row[2], 0); + let line = extract_i64(&row[3], 0); + let complexity = extract_i64(&row[4], 0); + let max_nesting_depth = extract_i64(&row[5], 0); + let start_line = extract_i64(&row[6], 0); + let end_line = extract_i64(&row[7], 0); + let lines = extract_i64(&row[8], 0); + let Some(generated_by) = extract_string(&row[9]) else { continue }; + + results.push(ComplexityMetric { + module, + name, + arity, + line, + complexity, + max_nesting_depth, + start_line, + end_line, + lines, + generated_by, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/cycles.rs b/db/src/queries/cycles.rs new file mode 100644 index 0000000..47a6105 --- /dev/null +++ b/db/src/queries/cycles.rs @@ -0,0 +1,93 @@ +//! Detect circular dependencies between modules using recursive queries. +//! +//! Uses CozoDB's recursive queries to: +//! 1. Build a deduplicated module dependency graph +//! 2. Find reachability (transitive closure) +//! 3. Detect modules that can reach themselves (cycles) +//! 4. Return cycle edges for reconstruction by the command + +use std::error::Error; + +use cozo::DataValue; + +use crate::db::{run_query, Params}; + +/// Edge in a cycle (from module -> to module) +#[derive(Debug, Clone)] +pub struct CycleEdge { + pub from: String, + pub to: String, +} + +/// Find all module pairs that form cycles +/// +/// Returns edges (from, to) where both modules are part of at least one cycle. +pub fn find_cycle_edges( + db: &cozo::DbInstance, + project: &str, + module_pattern: Option<&str>, +) -> Result, Box> { + // Build the recursive query for cycle detection + let script = r#" + # Build module dependency graph (deduplicated at module level) + module_deps[from, to] := + *calls{project, caller_module: from, callee_module: to}, + project == $project, + from != to + + # Find reachability (transitive closure) - what modules can be reached from each module + reaches[from, to] := module_deps[from, to] + reaches[from, to] := module_deps[from, mid], reaches[mid, to] + + # Find modules in cycles - modules that can reach themselves + in_cycle[module] := reaches[module, module] + + # Find cycle edges - direct edges between modules that are both in cycles + cycle_edge[from, to] := + module_deps[from, to], + in_cycle[from], + in_cycle[to] + + ?[from, to] := cycle_edge[from, to] + :order from, to + "#.to_string(); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params)?; + + // Parse results + let mut edges = Vec::new(); + + // Find column indices + let from_idx = rows + .headers + .iter() + .position(|h| h == "from") + .ok_or("Missing 'from' column")?; + let to_idx = rows + .headers + .iter() + .position(|h| h == "to") + .ok_or("Missing 'to' column")?; + + for row in &rows.rows { + if let (Some(DataValue::Str(from)), Some(DataValue::Str(to))) = + (row.get(from_idx), row.get(to_idx)) + { + // Apply module pattern filter if provided + if let Some(pattern) = module_pattern { + if !from.contains(pattern) && !to.contains(pattern) { + continue; + } + } + edges.push(CycleEdge { + from: from.to_string(), + to: to.to_string(), + }); + } + } + + Ok(edges) +} diff --git a/db/src/queries/depended_by.rs b/db/src/queries/depended_by.rs new file mode 100644 index 0000000..d8a645b --- /dev/null +++ b/db/src/queries/depended_by.rs @@ -0,0 +1,26 @@ +//! Find incoming module dependencies. +//! +//! This is a convenience wrapper around [`super::dependencies::find_dependencies`] with +//! [`DependencyDirection::Incoming`](super::dependencies::DependencyDirection::Incoming). + +use std::error::Error; + +use super::dependencies::{find_dependencies as query_dependencies, DependencyDirection}; +use crate::types::Call; + +pub fn find_dependents( + db: &cozo::DbInstance, + module_pattern: &str, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + query_dependencies( + db, + DependencyDirection::Incoming, + module_pattern, + project, + use_regex, + limit, + ) +} diff --git a/db/src/queries/dependencies.rs b/db/src/queries/dependencies.rs new file mode 100644 index 0000000..7266197 --- /dev/null +++ b/db/src/queries/dependencies.rs @@ -0,0 +1,114 @@ +//! Unified module dependency queries. +//! +//! This module provides a single query function that can find dependencies in either direction: +//! - `Outgoing`: Find modules that the matched module depends ON (imports/calls into) +//! - `Incoming`: Find modules that depend on (are depended BY) the matched module + +use std::error::Error; + +use cozo::DataValue; +use thiserror::Error; + +use crate::db::{extract_call_from_row, run_query, CallRowLayout, Params}; +use crate::types::Call; +use crate::query_builders::ConditionBuilder; + +#[derive(Error, Debug)] +pub enum DependencyError { + #[error("Dependency query failed: {message}")] + QueryFailed { message: String }, +} + +/// Direction of dependency analysis +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DependencyDirection { + /// Find modules that the matched module depends ON (outgoing dependencies) + /// Query: "What does module X call?" + Outgoing, + /// Find modules that depend on the matched module (incoming dependencies) + /// Query: "Who calls module X?" + Incoming, +} + +impl DependencyDirection { + /// Returns the field name to filter on based on direction + fn filter_field(&self) -> &'static str { + match self { + DependencyDirection::Outgoing => "caller_module", + DependencyDirection::Incoming => "callee_module", + } + } + + /// Returns the ORDER BY clause based on direction + fn order_clause(&self) -> &'static str { + match self { + DependencyDirection::Outgoing => { + "callee_module, callee_function, callee_arity, caller_module, caller_name, caller_arity, call_line" + } + DependencyDirection::Incoming => { + "caller_module, caller_name, caller_arity, callee_function, callee_arity, call_line" + } + } + } +} + +/// Find module dependencies in the specified direction. +/// +/// - `Outgoing`: Returns calls from the matched module to other modules +/// - `Incoming`: Returns calls from other modules to the matched module +/// +/// Self-references (calls within the same module) are excluded. +pub fn find_dependencies( + db: &cozo::DbInstance, + direction: DependencyDirection, + module_pattern: &str, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + let filter_field = direction.filter_field(); + let order_clause = direction.order_clause(); + + // Build module condition using the appropriate field name + let module_cond = + ConditionBuilder::new(filter_field, "module_pattern").build(use_regex); + + // Query calls with function_locations join for caller metadata, excluding self-references + // Filter out struct calls (callee_function != '%') + let script = format!( + r#" + ?[caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, + starts_with(caller_function, caller_name), + call_line >= caller_start_line, + call_line <= caller_end_line, + callee_function != '%', + {module_cond}, + caller_module != callee_module, + project == $project + :order {order_clause} + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert( + "module_pattern".to_string(), + DataValue::Str(module_pattern.into()), + ); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| DependencyError::QueryFailed { + message: e.to_string(), + })?; + + let layout = CallRowLayout::from_headers(&rows.headers)?; + let results = rows + .rows + .iter() + .filter_map(|row| extract_call_from_row(row, &layout)) + .collect(); + + Ok(results) +} diff --git a/db/src/queries/depends_on.rs b/db/src/queries/depends_on.rs new file mode 100644 index 0000000..44edfbf --- /dev/null +++ b/db/src/queries/depends_on.rs @@ -0,0 +1,26 @@ +//! Find outgoing module dependencies. +//! +//! This is a convenience wrapper around [`super::dependencies::find_dependencies`] with +//! [`DependencyDirection::Outgoing`](super::dependencies::DependencyDirection::Outgoing). + +use std::error::Error; + +use super::dependencies::{find_dependencies as query_dependencies, DependencyDirection}; +use crate::types::Call; + +pub fn find_dependencies( + db: &cozo::DbInstance, + module_pattern: &str, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + query_dependencies( + db, + DependencyDirection::Outgoing, + module_pattern, + project, + use_regex, + limit, + ) +} diff --git a/db/src/queries/duplicates.rs b/db/src/queries/duplicates.rs new file mode 100644 index 0000000..7d3adbd --- /dev/null +++ b/db/src/queries/duplicates.rs @@ -0,0 +1,106 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum DuplicatesError { + #[error("Duplicates query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function that has a duplicate implementation (same AST or source hash) +#[derive(Debug, Clone, Serialize)] +pub struct DuplicateFunction { + pub hash: String, + pub module: String, + pub name: String, + pub arity: i64, + pub line: i64, + pub file: String, +} + +pub fn find_duplicates( + db: &cozo::DbInstance, + project: &str, + module_pattern: Option<&str>, + use_regex: bool, + use_exact: bool, + exclude_generated: bool, +) -> Result, Box> { + // Choose hash field based on exact flag + let hash_field = if use_exact { "source_sha" } else { "ast_sha" }; + + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build optional generated filter + let generated_filter = if exclude_generated { + ", generated_by == \"\"".to_string() + } else { + String::new() + }; + + // Query to find duplicate hashes and their functions + let script = format!( + r#" + # Find hashes that appear more than once (count unique functions per hash) + hash_counts[{hash_field}, count(module)] := + *function_locations{{project, module, name, arity, {hash_field}, generated_by}}, + project == $project, + {hash_field} != "" + {generated_filter} + + # Get all functions with duplicate hashes + ?[{hash_field}, module, name, arity, line, file] := + *function_locations{{project, module, name, arity, line, file, {hash_field}, generated_by}}, + hash_counts[{hash_field}, cnt], + cnt > 1, + project == $project + {module_filter} + {generated_filter} + + :order {hash_field}, module, name, arity + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| DuplicatesError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(hash) = extract_string(&row[0]) else { continue }; + let Some(module) = extract_string(&row[1]) else { continue }; + let Some(name) = extract_string(&row[2]) else { continue }; + let arity = extract_i64(&row[3], 0); + let line = extract_i64(&row[4], 0); + let Some(file) = extract_string(&row[5]) else { continue }; + + results.push(DuplicateFunction { + hash, + module, + name, + arity, + line, + file, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/file.rs b/db/src/queries/file.rs new file mode 100644 index 0000000..30f7dff --- /dev/null +++ b/db/src/queries/file.rs @@ -0,0 +1,99 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum FileError { + #[error("File query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function defined in a file +#[derive(Debug, Clone, Serialize)] +pub struct FileFunctionDef { + pub module: String, + pub name: String, + pub arity: i64, + pub kind: String, + pub line: i64, + pub start_line: i64, + pub end_line: i64, + pub pattern: String, + pub guard: String, + #[serde(skip_serializing_if = "String::is_empty")] + pub file: String, +} + +/// Find all functions in modules matching a pattern +/// Returns a flat vec of functions with location info (for browse-module) +pub fn find_functions_in_module( + db: &cozo::DbInstance, + module_pattern: &str, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + // Build module filter + let module_filter = if use_regex { + "regex_matches(module, $module_pattern)" + } else { + "module == $module_pattern" + }; + + // Query to find all functions in matching modules + let script = format!( + r#" + ?[module, name, arity, kind, line, start_line, end_line, file, pattern, guard] := + *function_locations{{project, module, name, arity, line, file, kind, start_line, end_line, pattern, guard}}, + project == $project, + {module_filter} + + :order module, start_line, name, arity, line + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); + + let rows = run_query(db, &script, params).map_err(|e| FileError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + + for row in rows.rows { + if row.len() >= 10 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let arity = extract_i64(&row[2], 0); + let Some(kind) = extract_string(&row[3]) else { continue }; + let line = extract_i64(&row[4], 0); + let start_line = extract_i64(&row[5], 0); + let end_line = extract_i64(&row[6], 0); + let file = extract_string(&row[7]).unwrap_or_default(); + let pattern = extract_string(&row[8]).unwrap_or_default(); + let guard = extract_string(&row[9]).unwrap_or_default(); + + results.push(FileFunctionDef { + module, + name, + arity, + kind, + line, + start_line, + end_line, + pattern, + guard, + file, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/function.rs b/db/src/queries/function.rs new file mode 100644 index 0000000..2ff9f94 --- /dev/null +++ b/db/src/queries/function.rs @@ -0,0 +1,93 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; +use crate::query_builders::{ConditionBuilder, OptionalConditionBuilder}; + +#[derive(Error, Debug)] +pub enum FunctionError { + #[error("Function query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function signature +#[derive(Debug, Clone, Serialize)] +pub struct FunctionSignature { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub args: String, + pub return_type: String, +} + +pub fn find_functions( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: &str, + arity: Option, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + // Build query conditions using helpers + let module_cond = ConditionBuilder::new("module", "module_pattern").build(use_regex); + let function_cond = ConditionBuilder::new("name", "function_pattern") + .with_leading_comma() + .build(use_regex); + let arity_cond = OptionalConditionBuilder::new("arity", "arity") + .with_leading_comma() + .build(arity.is_some()); + let project_cond = ", project == $project"; + + let script = format!( + r#" + ?[project, module, name, arity, args, return_type] := + *functions{{project, module, name, arity, args, return_type}}, + {module_cond} + {function_cond} + {arity_cond} + {project_cond} + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); + params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); + if let Some(a) = arity { + params.insert("arity".to_string(), DataValue::from(a)); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| FunctionError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(project) = extract_string(&row[0]) else { continue }; + let Some(module) = extract_string(&row[1]) else { continue }; + let Some(name) = extract_string(&row[2]) else { continue }; + let arity = extract_i64(&row[3], 0); + let args = extract_string_or(&row[4], ""); + let return_type = extract_string_or(&row[5], ""); + + results.push(FunctionSignature { + project, + module, + name, + arity, + args, + return_type, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/hotspots.rs b/db/src/queries/hotspots.rs new file mode 100644 index 0000000..5f3a94c --- /dev/null +++ b/db/src/queries/hotspots.rs @@ -0,0 +1,292 @@ +use std::error::Error; + +use clap::ValueEnum; +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_f64, extract_i64, extract_string, run_query, Params}; + +/// What type of hotspots to find +#[derive(Debug, Clone, Copy, Default, ValueEnum)] +pub enum HotspotKind { + /// Functions with most incoming calls (most called) + #[default] + Incoming, + /// Functions with most outgoing calls (calls many things) + Outgoing, + /// Functions with highest total (incoming + outgoing) + Total, + /// Functions with highest ratio of incoming to outgoing calls (boundary functions) + Ratio, +} + +#[derive(Error, Debug)] +pub enum HotspotsError { + #[error("Hotspots query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function hotspot with call counts +#[derive(Debug, Clone, Serialize)] +pub struct Hotspot { + pub module: String, + pub function: String, + pub incoming: i64, + pub outgoing: i64, + pub total: i64, + pub ratio: f64, +} + +/// Get lines of code per module (sum of function line counts) +pub fn get_module_loc( + db: &cozo::DbInstance, + project: &str, + module_pattern: Option<&str>, + use_regex: bool, +) -> Result, Box> { + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + let script = format!( + r#" + # Calculate lines per function and sum by module + module_loc[module, sum(lines)] := + *function_locations{{project, module, start_line, end_line}}, + project == $project, + lines = end_line - start_line + 1 + {module_filter} + + ?[module, loc] := + module_loc[module, loc] + + :order -loc + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { + message: e.to_string(), + })?; + + let mut loc_map = std::collections::HashMap::new(); + for row in rows.rows { + if row.len() >= 2 { + if let Some(module) = extract_string(&row[0]) { + let loc = extract_i64(&row[1], 0); + loc_map.insert(module, loc); + } + } + } + + Ok(loc_map) +} + +/// Get function count per module +pub fn get_function_counts( + db: &cozo::DbInstance, + project: &str, + module_pattern: Option<&str>, + use_regex: bool, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + let script = format!( + r#" + func_counts[module, count(name)] := + *function_locations{{project, module, name}}, + project == $project + {module_filter} + + ?[module, func_count] := + func_counts[module, func_count] + + :order -func_count + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { + message: e.to_string(), + })?; + + let mut counts = std::collections::HashMap::new(); + for row in rows.rows { + if row.len() >= 2 { + if let Some(module) = extract_string(&row[0]) { + let count = extract_i64(&row[1], 0); + counts.insert(module, count); + } + } + } + + Ok(counts) +} + +pub fn find_hotspots( + db: &cozo::DbInstance, + kind: HotspotKind, + module_pattern: Option<&str>, + project: &str, + use_regex: bool, + limit: u32, + exclude_generated: bool, + require_outgoing: bool, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build optional generated filter + let generated_filter = if exclude_generated { + ", generated_by == \"\"".to_string() + } else { + String::new() + }; + + // Build optional outgoing filter (for boundaries - exclude leaf nodes) + let outgoing_filter = if require_outgoing { + ", outgoing > 0".to_string() + } else { + String::new() + }; + + let order_by = match kind { + HotspotKind::Incoming => "incoming", + HotspotKind::Outgoing => "outgoing", + HotspotKind::Total => "total", + HotspotKind::Ratio => "ratio", + }; + + // Query to find hotspots by counting incoming and outgoing calls + // We need to combine: + // 1. Functions as callers (outgoing) - count unique callees + // 2. Functions as callees (incoming) - count unique callers + // Note: caller_function may have arity suffix (e.g., "format/1") while callee_function doesn't ("format") + // We use callee_function as canonical name and match callers via starts_with + // Excludes recursive calls and deduplicates via intermediate relations + let script = format!( + r#" + # Get canonical function names (callee_function format, no arity suffix) + # A function's canonical name is how it appears as a callee + # Join with function_locations to filter generated functions + canonical[module, function] := + *calls{{project, callee_module, callee_function}}, + *function_locations{{project, module: callee_module, name: callee_function, generated_by}}, + project == $project, + module = callee_module, + function = callee_function + {generated_filter} + + # Distinct outgoing calls: match caller to canonical name + # caller_function is either "name" or "name/N", canonical_name is "name" + # Match: caller equals canonical OR starts with "canonical/" + distinct_outgoing[caller_module, canonical_name, callee_module, callee_function] := + *calls{{project, caller_module, caller_function, callee_module, callee_function}}, + canonical[caller_module, canonical_name], + project == $project, + (caller_function == canonical_name or starts_with(caller_function, concat(canonical_name, "/"))) + + # Count unique outgoing calls per function + outgoing_counts[module, function, count(callee_function)] := + distinct_outgoing[module, function, callee_module, callee_function] + + # Distinct incoming calls + distinct_incoming[callee_module, callee_function, caller_module, caller_function] := + *calls{{project, caller_module, caller_function, callee_module, callee_function}}, + canonical[callee_module, callee_function], + project == $project + + # Count unique incoming calls per function + incoming_counts[module, function, count(caller_function)] := + distinct_incoming[module, function, caller_module, caller_function] + + # Final query - functions with both incoming and outgoing + # Ratio = incoming / outgoing (high ratio = many callers, few dependencies = boundary) + ?[module, function, incoming, outgoing, total, ratio] := + incoming_counts[module, function, incoming], + outgoing_counts[module, function, outgoing], + total = incoming + outgoing, + ratio = if(outgoing == 0, 9999.0, incoming / outgoing) + {module_filter} + {outgoing_filter} + + # Functions with only incoming (no outgoing) - leaf nodes + # Excluded when require_outgoing is set + ?[module, function, incoming, outgoing, total, ratio] := + incoming_counts[module, function, incoming], + not outgoing_counts[module, function, _], + outgoing = 0, + total = incoming, + ratio = 9999.0 + {module_filter} + {outgoing_filter} + + # Functions with only outgoing (no incoming) + ?[module, function, incoming, outgoing, total, ratio] := + outgoing_counts[module, function, outgoing], + not incoming_counts[module, function, _], + incoming = 0, + total = outgoing, + ratio = 0.0 + {module_filter} + + :order -{order_by}, module, function + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(function) = extract_string(&row[1]) else { continue }; + let incoming = extract_i64(&row[2], 0); + let outgoing = extract_i64(&row[3], 0); + let total = extract_i64(&row[4], 0); + let ratio = extract_f64(&row[5], 0.0); + + results.push(Hotspot { + module, + function, + incoming, + outgoing, + total, + ratio, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/import.rs b/db/src/queries/import.rs new file mode 100644 index 0000000..b7147eb --- /dev/null +++ b/db/src/queries/import.rs @@ -0,0 +1,724 @@ +use std::error::Error; + +use cozo::{DataValue, DbInstance}; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{escape_string, escape_string_single, run_query, run_query_no_params, Params}; +use crate::queries::import_models::CallGraph; +use crate::queries::schema; + +/// Chunk size for batch database imports +const IMPORT_CHUNK_SIZE: usize = 500; + +#[derive(Error, Debug)] +pub enum ImportError { + #[error("Failed to read call graph file '{path}': {message}")] + FileReadFailed { path: String, message: String }, + + #[error("Failed to parse call graph JSON: {message}")] + JsonParseFailed { message: String }, + + #[allow(dead_code)] + #[error("Schema creation failed for '{relation}': {message}")] + SchemaCreationFailed { relation: String, message: String }, + + #[error("Failed to clear data: {message}")] + ClearFailed { message: String }, + + #[error("Failed to import {data_type}: {message}")] + ImportFailed { data_type: String, message: String }, +} + +/// Result of the import command execution +#[derive(Debug, Default, Serialize)] +pub struct ImportResult { + pub schemas: SchemaResult, + pub cleared: bool, + pub modules_imported: usize, + pub functions_imported: usize, + pub calls_imported: usize, + pub structs_imported: usize, + pub function_locations_imported: usize, + pub specs_imported: usize, + pub types_imported: usize, +} + +/// Result of schema creation +#[derive(Debug, Default, Serialize)] +pub struct SchemaResult { + pub created: Vec, + pub already_existed: Vec, +} + +pub fn create_schema(db: &DbInstance) -> Result> { + let mut result = SchemaResult::default(); + + let schema_results = schema::create_schema(db)?; + + for schema_result in schema_results { + if schema_result.created { + result.created.push(schema_result.relation); + } else { + result.already_existed.push(schema_result.relation); + } + } + + Ok(result) +} + +pub fn clear_project_data(db: &DbInstance, project: &str) -> Result<(), Box> { + // Delete all data for this project from each table + // Using :rm with a query that selects rows matching the project + let tables = [ + ("modules", "project, name"), + ("functions", "project, module, name, arity"), + ("calls", "project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column"), + ("struct_fields", "project, module, field"), + ("function_locations", "project, module, name, arity, line"), + ("specs", "project, module, name, arity"), + ("types", "project, module, name"), + ]; + + for (table, keys) in tables { + let script = format!( + r#" + ?[{keys}] := *{table}{{project: $project, {keys}}} + :rm {table} {{{keys}}} + "#, + table = table, + keys = keys + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + + run_query(db, &script, params).map_err(|e| ImportError::ClearFailed { + message: format!("Failed to clear {}: {}", table, e), + })?; + } + + Ok(()) +} + +/// Import rows in chunks into a CozoDB table +fn import_rows( + db: &DbInstance, + rows: Vec, + columns: &str, + table_spec: &str, + data_type: &str, +) -> Result> { + if rows.is_empty() { + return Ok(0); + } + + for chunk in rows.chunks(IMPORT_CHUNK_SIZE) { + let script = format!( + r#" + ?[{columns}] <- [{rows}] + :put {table_spec} + "#, + columns = columns, + rows = chunk.join(", "), + table_spec = table_spec + ); + + run_query_no_params(db, &script).map_err(|e| ImportError::ImportFailed { + data_type: data_type.to_string(), + message: e.to_string(), + })?; + } + + Ok(rows.len()) +} + +pub fn import_modules( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + // Collect unique modules from all data sources + let mut modules = std::collections::HashSet::new(); + modules.extend(graph.specs.keys().cloned()); + modules.extend(graph.function_locations.keys().cloned()); + modules.extend(graph.structs.keys().cloned()); + modules.extend(graph.types.keys().cloned()); + + let rows: Vec = modules + .iter() + .map(|m| { + format!( + r#"["{}", "{}", "", "unknown"]"#, + escape_string(project), + escape_string(m), + ) + }) + .collect(); + + import_rows( + db, + rows, + "project, name, file, source", + "modules { project, name => file, source }", + "modules", + ) +} + +pub fn import_functions( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let mut rows = Vec::new(); + + // Import functions from specs data + for (module, specs) in &graph.specs { + for spec in specs { + // Use first clause only + let (return_type, args) = spec + .clauses + .first() + .map(|c| (c.return_strings.join(" | "), c.input_strings.join(", "))) + .unwrap_or_default(); + + rows.push(format!( + r#"["{}", "{}", "{}", {}, "{}", "{}", "unknown"]"#, + escaped_project, + escape_string(module), + escape_string(&spec.name), + spec.arity, + escape_string(&return_type), + escape_string(&args), + )); + } + } + + import_rows( + db, + rows, + "project, module, name, arity, return_type, args, source", + "functions { project, module, name, arity => return_type, args, source }", + "functions", + ) +} + +pub fn import_calls( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let rows: Vec = graph + .calls + .iter() + .map(|call| { + let caller_kind = call.caller.kind.as_deref().unwrap_or(""); + let callee_args = call.callee.args.as_deref().unwrap_or(""); + + format!( + r#"["{}", "{}", "{}", "{}", "{}", {}, "{}", {}, {}, "{}", "{}", '{}']"#, + escaped_project, + escape_string(&call.caller.module), + escape_string(call.caller.function.as_deref().unwrap_or("")), + escape_string(&call.callee.module), + escape_string(&call.callee.function), + call.callee.arity, + escape_string(&call.caller.file), + call.caller.line.unwrap_or(0), + call.caller.column.unwrap_or(0), + escape_string(&call.call_type), + escape_string(caller_kind), + escape_string_single(callee_args), + ) + }) + .collect(); + + import_rows( + db, + rows, + "project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column, call_type, caller_kind, callee_args", + "calls { project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column => call_type, caller_kind, callee_args }", + "calls", + ) +} + +pub fn import_structs( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let mut rows = Vec::new(); + + for (module, def) in &graph.structs { + for field in &def.fields { + let inferred_type = field.inferred_type.as_deref().unwrap_or(""); + rows.push(format!( + r#"["{}", "{}", '{}', '{}', {}, "{}"]"#, + escaped_project, + escape_string(module), + escape_string_single(&field.field), + escape_string_single(&field.default), + field.required, + escape_string(inferred_type) + )); + } + } + + import_rows( + db, + rows, + "project, module, field, default_value, required, inferred_type", + "struct_fields { project, module, field => default_value, required, inferred_type }", + "struct_fields", + ) +} + +pub fn import_function_locations( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let mut rows = Vec::new(); + + for (module, functions) in &graph.function_locations { + for (_func_key, loc) in functions { + // Use deserialized fields directly from the JSON + let name = &loc.name; + let arity = loc.arity; + let line = loc.line; + + let source_file_absolute = loc.source_file_absolute.as_deref().unwrap_or(""); + let pattern = loc.pattern.as_deref().unwrap_or(""); + let guard = loc.guard.as_deref().unwrap_or(""); + let source_sha = loc.source_sha.as_deref().unwrap_or(""); + let ast_sha = loc.ast_sha.as_deref().unwrap_or(""); + let generated_by = loc.generated_by.as_deref().unwrap_or(""); + let macro_source = loc.macro_source.as_deref().unwrap_or(""); + + rows.push(format!( + r#"["{}", "{}", "{}", {}, {}, "{}", "{}", {}, "{}", {}, {}, '{}', '{}', "{}", "{}", {}, {}, "{}", "{}"]"#, + escaped_project, + escape_string(module), + escape_string(&name), + arity, + line, + escape_string(loc.file.as_deref().unwrap_or("")), + escape_string(source_file_absolute), + loc.column.unwrap_or(0), + escape_string(&loc.kind), + loc.start_line, + loc.end_line, + escape_string_single(pattern), + escape_string_single(guard), + escape_string(source_sha), + escape_string(ast_sha), + loc.complexity, + loc.max_nesting_depth, + escape_string(generated_by), + escape_string(macro_source), + )); + } + } + + import_rows( + db, + rows, + "project, module, name, arity, line, file, source_file_absolute, column, kind, start_line, end_line, pattern, guard, source_sha, ast_sha, complexity, max_nesting_depth, generated_by, macro_source", + "function_locations { project, module, name, arity, line => file, source_file_absolute, column, kind, start_line, end_line, pattern, guard, source_sha, ast_sha, complexity, max_nesting_depth, generated_by, macro_source }", + "function_locations", + ) +} + +pub fn import_specs( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let mut rows = Vec::new(); + + for (module, specs) in &graph.specs { + for spec in specs { + // Use first clause only (as per ticket recommendation) + let (inputs_string, return_string, full) = spec + .clauses + .first() + .map(|c| { + ( + c.input_strings.join(", "), + c.return_strings.join(" | "), + c.full.clone(), + ) + }) + .unwrap_or_default(); + + rows.push(format!( + r#"["{}", "{}", "{}", {}, "{}", {}, "{}", "{}", "{}"]"#, + escaped_project, + escape_string(module), + escape_string(&spec.name), + spec.arity, + escape_string(&spec.kind), + spec.line, + escape_string(&inputs_string), + escape_string(&return_string), + escape_string(&full), + )); + } + } + + import_rows( + db, + rows, + "project, module, name, arity, kind, line, inputs_string, return_string, full", + "specs { project, module, name, arity => kind, line, inputs_string, return_string, full }", + "specs", + ) +} + +pub fn import_types( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let escaped_project = escape_string(project); + let mut rows = Vec::new(); + + for (module, types) in &graph.types { + for type_def in types { + let params = type_def.params.join(", "); + + rows.push(format!( + r#"["{}", "{}", "{}", "{}", "{}", {}, '{}']"#, + escaped_project, + escape_string(module), + escape_string(&type_def.name), + escape_string(&type_def.kind), + escape_string(¶ms), + type_def.line, + escape_string_single(&type_def.definition), + )); + } + } + + import_rows( + db, + rows, + "project, module, name, kind, params, line, definition", + "types { project, module, name => kind, params, line, definition }", + "types", + ) +} + +/// Import a parsed CallGraph into the database. +/// +/// Creates schemas and imports all data (modules, functions, calls, structs, locations). +/// This is the core import logic used by both the CLI command and test utilities. +pub fn import_graph( + db: &DbInstance, + project: &str, + graph: &CallGraph, +) -> Result> { + let mut result = ImportResult::default(); + + result.schemas = create_schema(db)?; + result.modules_imported = import_modules(db, project, graph)?; + result.functions_imported = import_functions(db, project, graph)?; + result.calls_imported = import_calls(db, project, graph)?; + result.structs_imported = import_structs(db, project, graph)?; + result.function_locations_imported = import_function_locations(db, project, graph)?; + result.specs_imported = import_specs(db, project, graph)?; + result.types_imported = import_types(db, project, graph)?; + + Ok(result) +} + +/// Import a JSON string directly into the database. +/// +/// Convenience wrapper for tests that parses JSON and calls `import_graph`. +#[cfg(test)] +pub fn import_json_str( + db: &DbInstance, + content: &str, + project: &str, +) -> Result> { + let graph: CallGraph = + serde_json::from_str(content).map_err(|e| ImportError::JsonParseFailed { + message: e.to_string(), + })?; + + import_graph(db, project, &graph) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::db::{extract_string, open_db}; + use tempfile::NamedTempFile; + + // Test deserialization with all new fields present + #[test] + fn test_function_location_deserialize_with_new_fields() { + let json = r#"{ + "name": "test_func", + "arity": 2, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15, + "complexity": 5, + "max_nesting_depth": 3, + "generated_by": "Ecto.Schema", + "macro_source": "ecto/schema.ex" + }"#; + + let result: crate::queries::import_models::FunctionLocation = + serde_json::from_str(json).expect("Deserialization should succeed"); + + assert_eq!(result.complexity, 5); + assert_eq!(result.max_nesting_depth, 3); + assert_eq!(result.generated_by, Some("Ecto.Schema".to_string())); + assert_eq!(result.macro_source, Some("ecto/schema.ex".to_string())); + } + + // Test deserialization without optional fields (backward compatibility) + #[test] + fn test_function_location_deserialize_without_new_fields() { + let json = r#"{ + "name": "test_func", + "arity": 2, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15 + }"#; + + let result: crate::queries::import_models::FunctionLocation = + serde_json::from_str(json).expect("Deserialization should succeed"); + + // Should use defaults + assert_eq!(result.complexity, 1); // default_complexity + assert_eq!(result.max_nesting_depth, 0); // default + assert_eq!(result.generated_by, None); // default + assert_eq!(result.macro_source, None); // default + } + + // Test deserialization with empty string values + #[test] + fn test_function_location_deserialize_empty_strings() { + let json = r#"{ + "name": "test_func", + "arity": 2, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15, + "complexity": 1, + "max_nesting_depth": 0, + "generated_by": "", + "macro_source": "" + }"#; + + let result: crate::queries::import_models::FunctionLocation = + serde_json::from_str(json).expect("Deserialization should succeed"); + + // Empty strings should deserialize to None or empty string + assert_eq!(result.complexity, 1); + assert_eq!(result.max_nesting_depth, 0); + // Empty strings should parse as Some("") not None + assert_eq!(result.generated_by, Some("".to_string())); + assert_eq!(result.macro_source, Some("".to_string())); + } + + // Test import and database storage of new fields + #[test] + fn test_import_function_locations_with_new_fields() { + let json = r#"{ + "structs": {}, + "function_locations": { + "MyApp.Accounts": { + "process_data/2:20": { + "name": "process_data", + "arity": 2, + "file": "lib/accounts.ex", + "column": 5, + "kind": "def", + "line": 20, + "start_line": 20, + "end_line": 35, + "pattern": null, + "guard": null, + "source_sha": "", + "ast_sha": "", + "complexity": 7, + "max_nesting_depth": 4, + "generated_by": "Phoenix.Endpoint", + "macro_source": "phoenix/endpoint.ex" + } + } + }, + "calls": [], + "specs": {}, + "types": {} + }"#; + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); + + // Verify import succeeded + assert_eq!(result.function_locations_imported, 1); + + // Verify modules were created (MyApp.Accounts is inferred from function_locations) + assert!(result.modules_imported > 0); + + // If we got here, the new fields were successfully serialized and stored in the database + // The fact that import_graph succeeded means: + // 1. JSON deserialization worked with the new fields + // 2. import_function_locations() successfully formatted and inserted rows with 4 new fields + // 3. CozoDB schema accepted the data + } + + // Test import of struct fields with string-quoted atom syntax + #[test] + fn test_import_struct_fields_with_string_quoted_atoms() { + let json = r#"{ + "structs": { + "MyApp.User": { + "fields": [ + { + "field": "name", + "default": "nil", + "required": false, + "inferred_type": "String.t()" + }, + { + "field": ":\"user.id\"", + "default": "nil", + "required": false, + "inferred_type": "integer()" + }, + { + "field": ":\"first-name\"", + "default": ":\"foo.bar\"", + "required": true, + "inferred_type": "String.t()" + } + ] + } + }, + "function_locations": {}, + "calls": [], + "specs": {}, + "types": {} + }"#; + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); + + // Verify import succeeded + assert_eq!(result.structs_imported, 3); + + // Query the database to see what was actually stored + let query = r#" + ?[field, default_value] := *struct_fields{ + project: "test_project", + module: "MyApp.User", + field, + default_value + } + "#; + let rows = run_query_no_params(&db, query).expect("Query should succeed"); + + // Extract field names and defaults + let mut fields: Vec<(String, String)> = rows.rows.iter() + .filter_map(|row| { + let field = extract_string(&row[0])?; + let default = extract_string(&row[1])?; + Some((field, default)) + }) + .collect(); + fields.sort(); + + // Verify the string-quoted atom syntax is preserved in both field names and defaults + assert_eq!(fields.len(), 3); + assert_eq!(fields[0].0, r#":"first-name""#); + assert_eq!(fields[0].1, r#":"foo.bar""#); + assert_eq!(fields[1].0, r#":"user.id""#); + assert_eq!(fields[1].1, "nil"); + assert_eq!(fields[2].0, "name"); + assert_eq!(fields[2].1, "nil"); + } + + // Test import of types with string-quoted atoms in definition + #[test] + fn test_import_types_with_string_quoted_atoms() { + let json = r#"{ + "structs": {}, + "function_locations": {}, + "calls": [], + "specs": {}, + "types": { + "MyModule": [ + { + "name": "status", + "kind": "type", + "params": [], + "line": 5, + "definition": "@type status() :: :pending | :active | :\"special.status\"" + }, + { + "name": "config", + "kind": "type", + "params": [], + "line": 10, + "definition": "@type config() :: %{:\"api.key\" => String.t()}" + } + ] + } + }"#; + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); + + // Verify import succeeded + assert_eq!(result.types_imported, 2); + + // Query the database to see what was actually stored + let query = r#" + ?[name, definition] := *types{ + project: "test_project", + module: "MyModule", + name, + definition + } + "#; + let rows = run_query_no_params(&db, query).expect("Query should succeed"); + + // Extract type definitions + let mut types: Vec<(String, String)> = rows.rows.iter() + .filter_map(|row| { + let name = extract_string(&row[0])?; + let definition = extract_string(&row[1])?; + Some((name, definition)) + }) + .collect(); + types.sort(); + + // Verify the string-quoted atom syntax is preserved in definitions + assert_eq!(types.len(), 2); + assert_eq!(types[0].0, "config"); + assert_eq!(types[0].1, r#"@type config() :: %{:"api.key" => String.t()}"#); + assert_eq!(types[1].0, "status"); + assert_eq!(types[1].1, r#"@type status() :: :pending | :active | :"special.status""#); + } +} diff --git a/db/src/queries/import_models.rs b/db/src/queries/import_models.rs new file mode 100644 index 0000000..d500e06 --- /dev/null +++ b/db/src/queries/import_models.rs @@ -0,0 +1,145 @@ +//! JSON import structures for call graph data. +//! +//! These types are used to deserialize the JSON output from the Elixir +//! call graph extractor during the import process. + +use serde::Deserialize; +use std::collections::HashMap; + +#[derive(Debug, Deserialize)] +pub struct CallGraph { + pub structs: HashMap, + pub function_locations: HashMap>, + pub calls: Vec, + #[serde(default)] + pub specs: HashMap>, + #[serde(default)] + pub types: HashMap>, +} + +#[derive(Debug, Deserialize)] +pub struct StructDef { + pub fields: Vec, +} + +#[derive(Debug, Deserialize)] +pub struct StructField { + pub default: String, + pub field: String, + pub required: bool, + pub inferred_type: Option, +} + +/// Function location with clause-level detail. +/// +/// The new format stores each function clause as a separate entry keyed by `function/arity:line`. +/// Fields `name` and `arity` are deserialized directly from the JSON. +#[derive(Debug, Deserialize)] +pub struct FunctionLocation { + pub name: String, + pub arity: u32, + /// Relative file path (accepts either "file" or "source_file" from JSON) + #[serde(alias = "source_file")] + pub file: Option, + #[serde(rename = "source_file_absolute")] + pub source_file_absolute: Option, + pub column: Option, + pub kind: String, + pub line: u32, + pub start_line: u32, + pub end_line: u32, + pub pattern: Option, + pub guard: Option, + pub source_sha: Option, + pub ast_sha: Option, + #[serde(default = "default_complexity")] + pub complexity: u32, + #[serde(default)] + pub max_nesting_depth: u32, + #[serde(default)] + pub generated_by: Option, + #[serde(default)] + pub macro_source: Option, +} + +fn default_complexity() -> u32 { + 1 +} + +#[derive(Debug, Deserialize)] +pub struct Call { + pub caller: Caller, + pub callee: Callee, + #[serde(rename = "type")] + pub call_type: String, +} + +#[derive(Debug, Deserialize)] +pub struct Caller { + pub module: String, + pub function: Option, + pub file: String, + pub line: Option, + pub column: Option, + /// Function kind: "def", "defp", "defmacro", "defmacrop" + pub kind: Option, +} + +#[derive(Debug, Deserialize)] +pub struct Callee { + pub module: String, + pub function: String, + pub arity: u32, + /// Argument names (comma-separated in source) + pub args: Option, +} + +/// A @spec or @callback definition. +/// +/// Format from extracted_trace.json: +/// ```json +/// { +/// "arity": 1, +/// "line": 19, +/// "name": "function_name", +/// "kind": "spec", +/// "clauses": [{ "full": "...", "inputs_string": [...], "return_string": "..." }] +/// } +/// ``` +#[derive(Debug, Deserialize)] +pub struct Spec { + pub name: String, + pub arity: u32, + pub line: u32, + pub kind: String, + pub clauses: Vec, +} + +/// A single clause within a spec definition. +#[derive(Debug, Deserialize)] +pub struct SpecClause { + pub full: String, + pub input_strings: Vec, + pub return_strings: Vec, +} + +/// A @type, @typep, or @opaque definition. +/// +/// Format from extracted_trace.json: +/// ```json +/// { +/// "line": 341, +/// "name": "socket_ref", +/// "params": [], +/// "kind": "type", +/// "definition": "@type socket_ref() :: {Pid, module(), binary(), binary(), binary()}" +/// } +/// ``` +#[derive(Debug, Deserialize)] +pub struct TypeDef { + pub name: String, + pub kind: String, + pub line: u32, + pub params: Vec, + pub definition: String, +} diff --git a/db/src/queries/large_functions.rs b/db/src/queries/large_functions.rs new file mode 100644 index 0000000..3bb1715 --- /dev/null +++ b/db/src/queries/large_functions.rs @@ -0,0 +1,103 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum LargeFunctionsError { + #[error("Large functions query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function with line count information +#[derive(Debug, Clone, Serialize)] +pub struct LargeFunction { + pub module: String, + pub name: String, + pub arity: i64, + pub start_line: i64, + pub end_line: i64, + pub lines: i64, + pub file: String, + pub generated_by: String, +} + +pub fn find_large_functions( + db: &cozo::DbInstance, + min_lines: i64, + module_pattern: Option<&str>, + project: &str, + use_regex: bool, + include_generated: bool, + limit: u32, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build optional generated filter + let generated_filter = if include_generated { + String::new() + } else { + ", generated_by == \"\"".to_string() + }; + + let script = format!( + r#" + ?[module, name, arity, start_line, end_line, lines, file, generated_by] := + *function_locations{{project, module, name, arity, line, start_line, end_line, file, generated_by}}, + project == $project, + lines = end_line - start_line + 1, + lines >= $min_lines + {module_filter} + {generated_filter} + + :order -lines, module, name + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert("min_lines".to_string(), DataValue::from(min_lines)); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| LargeFunctionsError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 8 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let arity = extract_i64(&row[2], 0); + let start_line = extract_i64(&row[3], 0); + let end_line = extract_i64(&row[4], 0); + let lines = extract_i64(&row[5], 0); + let Some(file) = extract_string(&row[6]) else { continue }; + let Some(generated_by) = extract_string(&row[7]) else { continue }; + + results.push(LargeFunction { + module, + name, + arity, + start_line, + end_line, + lines, + file, + generated_by, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/location.rs b/db/src/queries/location.rs new file mode 100644 index 0000000..16d3c08 --- /dev/null +++ b/db/src/queries/location.rs @@ -0,0 +1,121 @@ +use std::error::Error; + +use cozo::{DataValue, Num}; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; + +#[derive(Error, Debug)] +pub enum LocationError { + #[error("Location query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function location result +#[derive(Debug, Clone, Serialize)] +pub struct FunctionLocation { + pub project: String, + pub file: String, + pub line: i64, + pub start_line: i64, + pub end_line: i64, + pub module: String, + pub kind: String, + pub name: String, + pub arity: i64, + pub pattern: String, + pub guard: String, +} + +pub fn find_locations( + db: &cozo::DbInstance, + module_pattern: Option<&str>, + function_pattern: &str, + arity: Option, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + // Build the query based on whether we're using regex or exact match + let fn_cond = if use_regex { + "regex_matches(name, $function_pattern)".to_string() + } else { + "name == $function_pattern".to_string() + }; + + let module_cond = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", module == $module_pattern".to_string(), + None => String::new(), + }; + + let arity_cond = if arity.is_some() { + ", arity == $arity" + } else { + "" + }; + + let project_cond = ", project == $project"; + + let script = format!( + r#" + ?[project, file, line, start_line, end_line, module, kind, name, arity, pattern, guard] := + *function_locations{{project, module, name, arity, line, file, kind, start_line, end_line, pattern, guard}}, + {fn_cond} + {module_cond} + {arity_cond} + {project_cond} + :order module, name, arity, line + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); + if let Some(mod_pat) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(mod_pat.into())); + } + if let Some(a) = arity { + params.insert("arity".to_string(), DataValue::Num(Num::Int(a))); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| LocationError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 11 { + // Order matches query: project, file, line, start_line, end_line, module, kind, name, arity, pattern, guard + let Some(project) = extract_string(&row[0]) else { continue }; + let Some(file) = extract_string(&row[1]) else { continue }; + let line = extract_i64(&row[2], 0); + let start_line = extract_i64(&row[3], 0); + let end_line = extract_i64(&row[4], 0); + let Some(module) = extract_string(&row[5]) else { continue }; + let kind = extract_string_or(&row[6], ""); + let Some(name) = extract_string(&row[7]) else { continue }; + let arity = extract_i64(&row[8], 0); + let pattern = extract_string_or(&row[9], ""); + let guard = extract_string_or(&row[10], ""); + + results.push(FunctionLocation { + project, + file, + line, + start_line, + end_line, + module, + kind, + name, + arity, + pattern, + guard, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/many_clauses.rs b/db/src/queries/many_clauses.rs new file mode 100644 index 0000000..10408da --- /dev/null +++ b/db/src/queries/many_clauses.rs @@ -0,0 +1,105 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum ManyClausesError { + #[error("Many clauses query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function with clause count information +#[derive(Debug, Clone, Serialize)] +pub struct ManyClauses { + pub module: String, + pub name: String, + pub arity: i64, + pub clauses: i64, + pub first_line: i64, + pub last_line: i64, + pub file: String, + pub generated_by: String, +} + +pub fn find_many_clauses( + db: &cozo::DbInstance, + min_clauses: i64, + module_pattern: Option<&str>, + project: &str, + use_regex: bool, + include_generated: bool, + limit: u32, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build optional generated filter + let generated_filter = if include_generated { + String::new() + } else { + ", generated_by == \"\"".to_string() + }; + + let script = format!( + r#" + clause_counts[module, name, arity, count(line), min(start_line), max(end_line), file, generated_by] := + *function_locations{{project, module, name, arity, line, start_line, end_line, file, generated_by}}, + project == $project + {module_filter} + {generated_filter} + + ?[module, name, arity, clauses, first_line, last_line, file, generated_by] := + clause_counts[module, name, arity, clauses, first_line, last_line, file, generated_by], + clauses >= $min_clauses + + :order -clauses, module, name + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert("min_clauses".to_string(), DataValue::from(min_clauses)); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| ManyClausesError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 8 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let arity = extract_i64(&row[2], 0); + let clauses = extract_i64(&row[3], 0); + let first_line = extract_i64(&row[4], 0); + let last_line = extract_i64(&row[5], 0); + let Some(file) = extract_string(&row[6]) else { continue }; + let Some(generated_by) = extract_string(&row[7]) else { continue }; + + results.push(ManyClauses { + module, + name, + arity, + clauses, + first_line, + last_line, + file, + generated_by, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/mod.rs b/db/src/queries/mod.rs new file mode 100644 index 0000000..8b45fe1 --- /dev/null +++ b/db/src/queries/mod.rs @@ -0,0 +1,81 @@ +//! Database query modules for call graph analysis. +//! +//! Each module contains CozoScript queries and result parsing for a specific +//! command. Queries execute against a CozoDB instance and return typed results. +//! +//! # Query Categories +//! +//! ## Data Import +//! - [`import`] - Import JSON call graph data into database relations +//! +//! ## Basic Lookups +//! - [`location`] - Find function definition locations by name +//! - [`function`] - Get function signatures with type information +//! - [`search`] - Full-text search across functions, specs, and types +//! - [`file`] - List all functions defined in a module/file +//! +//! ## Call Graph Traversal +//! - [`calls_from`] - Find all functions called by a given function +//! - [`calls_to`] - Find all callers of a given function +//! - [`trace`] - Forward call trace to specified depth +//! - [`reverse_trace`] - Backward call trace (who calls this, recursively) +//! - [`path`] - Find call path between two functions +//! +//! ## Dependency Analysis +//! - [`depends_on`] - Modules that a given module depends on +//! - [`depended_by`] - Modules that depend on a given module +//! +//! ## Code Quality +//! - [`unused`] - Find functions that are never called +//! - [`hotspots`] - Find most-called functions (high fan-in) +//! +//! ## Type System +//! - [`specs`] - Query @spec and @callback definitions +//! - [`types`] - Query @type, @typep, and @opaque definitions +//! - [`structs`] - Query struct definitions with field info +//! +//! # Performance +//! +//! All queries are indexed by module/function names. Most lookups are O(log n) +//! with O(m) result iteration where m is result count. Trace queries may be +//! O(n * depth) in worst case for highly connected graphs. +//! +//! # Query Pattern +//! +//! Each query module exports a single `find_*` or `*_query` function that: +//! 1. Builds a CozoScript query string with interpolated parameters +//! 2. Executes via `db.run_script()` +//! 3. Extracts results into typed Rust structs +//! +//! Parameters are escaped using [`crate::db::escape_string`] to prevent injection. + +pub mod accepts; +pub mod calls; +pub mod calls_from; +pub mod calls_to; +pub mod clusters; +pub mod complexity; +pub mod cycles; +pub mod depended_by; +pub mod dependencies; +pub mod depends_on; +pub mod duplicates; +pub mod file; +pub mod function; +pub mod hotspots; +pub mod import; +pub mod import_models; +pub mod large_functions; +pub mod location; +pub mod many_clauses; +pub mod path; +pub mod returns; +pub mod reverse_trace; +pub mod schema; +pub mod search; +pub mod specs; +pub mod struct_usage; +pub mod structs; +pub mod trace; +pub mod types; +pub mod unused; \ No newline at end of file diff --git a/db/src/queries/path.rs b/db/src/queries/path.rs new file mode 100644 index 0000000..503ca63 --- /dev/null +++ b/db/src/queries/path.rs @@ -0,0 +1,245 @@ +use std::collections::HashMap; +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; +use crate::query_builders::OptionalConditionBuilder; + +#[derive(Error, Debug)] +pub enum PathError { + #[error("Path query failed: {message}")] + QueryFailed { message: String }, +} + +/// A single step in a call path +#[derive(Debug, Clone, Serialize)] +pub struct PathStep { + pub depth: i64, + pub caller_module: String, + pub caller_function: String, + pub callee_module: String, + pub callee_function: String, + pub callee_arity: i64, + pub file: String, + pub line: i64, +} + +/// A complete path from source to target +#[derive(Debug, Clone, Serialize)] +pub struct CallPath { + pub steps: Vec, +} + +#[allow(clippy::too_many_arguments)] +pub fn find_paths( + db: &cozo::DbInstance, + from_module: &str, + from_function: &str, + from_arity: Option, + to_module: &str, + to_function: &str, + to_arity: Option, + project: &str, + max_depth: u32, + limit: u32, +) -> Result, Box> { + // Build conditions using the ConditionBuilder utilities + let from_arity_cond = OptionalConditionBuilder::new("caller_arity", "from_arity") + .when_none("true") + .build(from_arity.is_some()); + + let to_arity_cond = OptionalConditionBuilder::new("callee_arity", "to_arity") + .when_none("true") + .build(to_arity.is_some()); + + // Simpler approach: trace forward from source to find all reachable calls, + // then filter to paths that end at the target. + // Returns edges on valid paths (may include multiple paths if they exist). + // Joins with function_locations to get caller arity for filtering. + let script = format!( + r#" + # Base case: direct calls from the source function + # Join with function_locations to get caller arity + # Uses starts_with to handle both "func" and "func/2" formats in caller_function + trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity}}, + starts_with(caller_function, caller_name), + caller_module == $from_module, + starts_with(caller_function, $from_function), + {from_arity_cond}, + project == $project, + depth = 1 + + # Recursive case: continue from callees we've found + trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := + trace[prev_depth, _, _, prev_callee_module, prev_callee_function, _, _, _], + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line}}, + caller_module == prev_callee_module, + starts_with(caller_function, prev_callee_function), + prev_depth < {max_depth}, + depth = prev_depth + 1, + project == $project + + # Find the depth at which we reach the target + target_depth[d] := + trace[d, _, _, callee_module, callee_function, callee_arity, _, _], + callee_module == $to_module, + starts_with(callee_function, $to_function), + {to_arity_cond} + + # Only return edges at depths <= minimum target depth (edges on valid paths) + ?[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := + trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line], + target_depth[min_d], + depth <= min_d + + :order depth, caller_module, caller_function, callee_module, callee_function + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("from_module".to_string(), DataValue::Str(from_module.into())); + params.insert("from_function".to_string(), DataValue::Str(from_function.into())); + params.insert("to_module".to_string(), DataValue::Str(to_module.into())); + params.insert("to_function".to_string(), DataValue::Str(to_function.into())); + if let Some(a) = from_arity { + params.insert("from_arity".to_string(), DataValue::from(a)); + } + if let Some(a) = to_arity { + params.insert("to_arity".to_string(), DataValue::from(a)); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| PathError::QueryFailed { + message: e.to_string(), + })?; + + // Parse all edges from the query result + let mut edges: Vec = Vec::new(); + + for row in rows.rows { + if row.len() >= 8 { + let depth = extract_i64(&row[0], 0); + let Some(caller_module) = extract_string(&row[1]) else { continue }; + let Some(caller_function) = extract_string(&row[2]) else { continue }; + let Some(callee_module) = extract_string(&row[3]) else { continue }; + let Some(callee_function) = extract_string(&row[4]) else { continue }; + let callee_arity = extract_i64(&row[5], 0); + let Some(file) = extract_string(&row[6]) else { continue }; + let line = extract_i64(&row[7], 0); + + edges.push(PathStep { + depth, + caller_module, + caller_function, + callee_module, + callee_function, + callee_arity, + file, + line, + }); + } + } + + if edges.is_empty() { + return Ok(vec![]); + } + + // Build adjacency list: (module, function) -> list of edges from that node + // Key is (caller_module, caller_function), value is list of edges + let mut adj: HashMap<(String, String), Vec<&PathStep>> = HashMap::new(); + for edge in &edges { + adj.entry((edge.caller_module.clone(), edge.caller_function.clone())) + .or_default() + .push(edge); + } + + // Find all paths using DFS from source to target + let mut all_paths: Vec = Vec::new(); + let mut current_path: Vec = Vec::new(); + + // Find starting edges (depth 1, from the source function) + let starting_edges: Vec<&PathStep> = edges.iter().filter(|e| e.depth == 1).collect(); + + for start_edge in starting_edges { + current_path.clear(); + dfs_find_paths( + start_edge, + to_module, + to_function, + to_arity, + &adj, + &mut current_path, + &mut all_paths, + limit as usize, + ); + } + + Ok(all_paths) +} + +/// DFS to find all paths from current edge to target +fn dfs_find_paths( + current_edge: &PathStep, + to_module: &str, + to_function: &str, + to_arity: Option, + adj: &HashMap<(String, String), Vec<&PathStep>>, + current_path: &mut Vec, + all_paths: &mut Vec, + limit: usize, +) { + // Add current edge to path + current_path.push(current_edge.clone()); + + // Check if we reached the target + let at_target = current_edge.callee_module == to_module + && current_edge.callee_function == to_function + && to_arity.map_or(true, |a| current_edge.callee_arity == a); + + if at_target { + // Found a complete path + all_paths.push(CallPath { + steps: current_path.clone(), + }); + } else if all_paths.len() < limit { + // Continue searching from the callee + // Find edges where caller matches our callee + // Note: caller_function has arity suffix, callee_function doesn't + // So we need to find edges where caller starts with our callee_function + for (key, next_edges) in adj.iter() { + if key.0 == current_edge.callee_module && key.1.starts_with(¤t_edge.callee_function) { + for next_edge in next_edges { + // Avoid cycles - check if we've already visited this exact edge + let already_visited = current_path.iter().any(|e| { + e.caller_module == next_edge.caller_module + && e.caller_function == next_edge.caller_function + && e.callee_module == next_edge.callee_module + && e.callee_function == next_edge.callee_function + }); + + if !already_visited && all_paths.len() < limit { + dfs_find_paths( + next_edge, + to_module, + to_function, + to_arity, + adj, + current_path, + all_paths, + limit, + ); + } + } + } + } + } + + // Backtrack + current_path.pop(); +} diff --git a/db/src/queries/returns.rs b/db/src/queries/returns.rs new file mode 100644 index 0000000..e4248c7 --- /dev/null +++ b/db/src/queries/returns.rs @@ -0,0 +1,104 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum ReturnsError { + #[error("Returns query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function with its return type specification +#[derive(Debug, Clone, Serialize)] +pub struct ReturnEntry { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub return_string: String, + pub line: i64, +} + +pub fn find_returns( + db: &cozo::DbInstance, + pattern: &str, + project: &str, + use_regex: bool, + module_pattern: Option<&str>, + limit: u32, +) -> Result, Box> { + // Build return string filter + let match_fn = if use_regex { + "regex_matches(return_string, $pattern)" + } else { + "str_includes(return_string, $pattern)" + }; + + // Build module filter + let module_filter = match module_pattern { + Some(_) if use_regex => "regex_matches(module, $module_pattern)", + Some(_) => "str_includes(module, $module_pattern)", + None => "true", + }; + + let script = format!( + r#" + ?[project, module, name, arity, return_string, line] := + *specs{{project, module, name, arity, return_string, line}}, + project == $project, + {match_fn}, + {module_filter} + + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("pattern".to_string(), DataValue::Str(pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + if let Some(mod_pat) = module_pattern { + params.insert( + "module_pattern".to_string(), + DataValue::Str(mod_pat.into()), + ); + } + + let rows = run_query(db, &script, params).map_err(|e| ReturnsError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(project) = extract_string(&row[0]) else { + continue; + }; + let Some(module) = extract_string(&row[1]) else { + continue; + }; + let Some(name) = extract_string(&row[2]) else { + continue; + }; + let arity = extract_i64(&row[3], 0); + let return_string = extract_string(&row[4]).unwrap_or_default(); + let line = extract_i64(&row[5], 0); + + results.push(ReturnEntry { + project, + module, + name, + arity, + return_string, + line, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/reverse_trace.rs b/db/src/queries/reverse_trace.rs new file mode 100644 index 0000000..1c65ea4 --- /dev/null +++ b/db/src/queries/reverse_trace.rs @@ -0,0 +1,140 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; +use crate::query_builders::{ConditionBuilder, OptionalConditionBuilder}; + +#[derive(Error, Debug)] +pub enum ReverseTraceError { + #[error("Reverse trace query failed: {message}")] + QueryFailed { message: String }, +} + +/// A single step in the reverse call chain +#[derive(Debug, Clone, Serialize)] +pub struct ReverseTraceStep { + pub depth: i64, + pub caller_module: String, + pub caller_function: String, + pub caller_arity: i64, + pub caller_kind: String, + pub caller_start_line: i64, + pub caller_end_line: i64, + pub callee_module: String, + pub callee_function: String, + pub callee_arity: i64, + pub file: String, + pub line: i64, +} + +pub fn reverse_trace_calls( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: &str, + arity: Option, + project: &str, + use_regex: bool, + max_depth: u32, + limit: u32, +) -> Result, Box> { + // Build the starting conditions for the recursive query using helpers + // For reverse trace, we match on the callee (target) + let module_cond = ConditionBuilder::new("callee_module", "module_pattern").build(use_regex); + let function_cond = ConditionBuilder::new("callee_function", "function_pattern").build(use_regex); + let arity_cond = OptionalConditionBuilder::new("callee_arity", "arity") + .when_none("true") + .build(arity.is_some()); + + // Recursive query to trace call chains backwards, joined with function_locations for caller metadata + // Base case: calls TO the target function + // Recursive case: calls TO the callers we've found + let script = format!( + r#" + # Base case: calls to the target function, joined with function_locations + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, + starts_with(caller_function, caller_name), + call_line >= caller_start_line, + call_line <= caller_end_line, + {module_cond}, + {function_cond}, + project == $project, + {arity_cond}, + depth = 1 + + # Recursive case: calls to the callers we've found + # Note: prev_caller_function has arity suffix (e.g., "foo/2") but callee_function doesn't (e.g., "foo") + # So we use starts_with to match prev_caller_function starting with callee_function + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + trace[prev_depth, prev_caller_module, prev_caller_name, prev_caller_arity, _, _, _, _, _, _, _, _], + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, + callee_module == prev_caller_module, + callee_function == prev_caller_name, + callee_arity == prev_caller_arity, + starts_with(caller_function, caller_name), + call_line >= caller_start_line, + call_line <= caller_end_line, + prev_depth < {max_depth}, + depth = prev_depth + 1, + project == $project + + ?[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] + + :order depth, caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); + params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); + if let Some(a) = arity { + params.insert("arity".to_string(), DataValue::from(a)); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| ReverseTraceError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 12 { + let depth = extract_i64(&row[0], 0); + let Some(caller_module) = extract_string(&row[1]) else { continue }; + let Some(caller_function) = extract_string(&row[2]) else { continue }; + let caller_arity = extract_i64(&row[3], 0); + let caller_kind = extract_string_or(&row[4], ""); + let caller_start_line = extract_i64(&row[5], 0); + let caller_end_line = extract_i64(&row[6], 0); + let Some(callee_module) = extract_string(&row[7]) else { continue }; + let Some(callee_function) = extract_string(&row[8]) else { continue }; + let callee_arity = extract_i64(&row[9], 0); + let Some(file) = extract_string(&row[10]) else { continue }; + let line = extract_i64(&row[11], 0); + + results.push(ReverseTraceStep { + depth, + caller_module, + caller_function, + caller_arity, + caller_kind, + caller_start_line, + caller_end_line, + callee_module, + callee_function, + callee_arity, + file, + line, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/schema.rs b/db/src/queries/schema.rs new file mode 100644 index 0000000..3324e60 --- /dev/null +++ b/db/src/queries/schema.rs @@ -0,0 +1,180 @@ +//! Database schema creation and management. +//! +//! This module provides shared schema utilities used by both the import +//! and setup commands. It defines the database schema for all relations +//! and provides functions to create, check, and drop them. + +use std::error::Error; +use cozo::DbInstance; +use crate::db::try_create_relation; + +// Schema definitions + +pub const SCHEMA_MODULES: &str = r#" +:create modules { + project: String, + name: String + => + file: String default "", + source: String default "unknown" +} +"#; + +pub const SCHEMA_FUNCTIONS: &str = r#" +:create functions { + project: String, + module: String, + name: String, + arity: Int + => + return_type: String default "", + args: String default "", + source: String default "unknown" +} +"#; + +pub const SCHEMA_CALLS: &str = r#" +:create calls { + project: String, + caller_module: String, + caller_function: String, + callee_module: String, + callee_function: String, + callee_arity: Int, + file: String, + line: Int, + column: Int + => + call_type: String default "remote", + caller_kind: String default "", + callee_args: String default "" +} +"#; + +pub const SCHEMA_STRUCT_FIELDS: &str = r#" +:create struct_fields { + project: String, + module: String, + field: String + => + default_value: String, + required: Bool, + inferred_type: String +} +"#; + +pub const SCHEMA_FUNCTION_LOCATIONS: &str = r#" +:create function_locations { + project: String, + module: String, + name: String, + arity: Int, + line: Int + => + file: String, + source_file_absolute: String default "", + column: Int, + kind: String, + start_line: Int, + end_line: Int, + pattern: String default "", + guard: String default "", + source_sha: String default "", + ast_sha: String default "", + complexity: Int default 1, + max_nesting_depth: Int default 0, + generated_by: String default "", + macro_source: String default "" +} +"#; + +pub const SCHEMA_SPECS: &str = r#" +:create specs { + project: String, + module: String, + name: String, + arity: Int + => + kind: String, + line: Int, + inputs_string: String default "", + return_string: String default "", + full: String default "" +} +"#; + +pub const SCHEMA_TYPES: &str = r#" +:create types { + project: String, + module: String, + name: String + => + kind: String, + params: String default "", + line: Int, + definition: String default "" +} +"#; + +/// Result of schema creation operation +#[derive(Debug, Clone)] +pub struct SchemaCreationResult { + pub relation: String, + pub created: bool, +} + +/// Create all database schemas. +/// +/// Returns a list of all relations with their creation status. +/// If a relation already exists, returns Ok with created=false for that relation. +pub fn create_schema(db: &DbInstance) -> Result, Box> { + let mut result = Vec::new(); + + let schemas = [ + ("modules", SCHEMA_MODULES), + ("functions", SCHEMA_FUNCTIONS), + ("calls", SCHEMA_CALLS), + ("struct_fields", SCHEMA_STRUCT_FIELDS), + ("function_locations", SCHEMA_FUNCTION_LOCATIONS), + ("specs", SCHEMA_SPECS), + ("types", SCHEMA_TYPES), + ]; + + for (name, script) in schemas { + let created = try_create_relation(db, script)?; + result.push(SchemaCreationResult { + relation: name.to_string(), + created, + }); + } + + Ok(result) +} + +/// Get list of all relation names managed by this schema +pub fn relation_names() -> Vec<&'static str> { + vec![ + "modules", + "functions", + "calls", + "struct_fields", + "function_locations", + "specs", + "types", + ] +} + +/// Get schema script for a specific relation by name +#[allow(dead_code)] +pub fn schema_for_relation(name: &str) -> Option<&'static str> { + match name { + "modules" => Some(SCHEMA_MODULES), + "functions" => Some(SCHEMA_FUNCTIONS), + "calls" => Some(SCHEMA_CALLS), + "struct_fields" => Some(SCHEMA_STRUCT_FIELDS), + "function_locations" => Some(SCHEMA_FUNCTION_LOCATIONS), + "specs" => Some(SCHEMA_SPECS), + "types" => Some(SCHEMA_TYPES), + _ => None, + } +} diff --git a/db/src/queries/search.rs b/db/src/queries/search.rs new file mode 100644 index 0000000..13f12e0 --- /dev/null +++ b/db/src/queries/search.rs @@ -0,0 +1,117 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; + +#[derive(Error, Debug)] +pub enum SearchError { + #[error("Search failed: {message}")] + QueryFailed { message: String }, +} + +/// A module search result +#[derive(Debug, Clone, Serialize)] +pub struct ModuleResult { + pub project: String, + pub name: String, + pub source: String, +} + +/// A function search result +#[derive(Debug, Clone, Serialize)] +pub struct FunctionResult { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub return_type: String, +} + +pub fn search_modules( + db: &cozo::DbInstance, + pattern: &str, + project: &str, + limit: u32, + use_regex: bool, +) -> Result, Box> { + let match_fn = if use_regex { "regex_matches" } else { "str_includes" }; + let script = format!( + r#" + ?[project, name, source] := *modules{{project, name, source}}, + project = $project, + {match_fn}(name, $pattern) + :limit {limit} + :order name + "#, + ); + + let mut params = Params::new(); + params.insert("pattern".to_string(), DataValue::Str(pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| SearchError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 3 { + let Some(project) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let source = extract_string_or(&row[2], "unknown"); + results.push(ModuleResult { project, name, source }); + } + } + + Ok(results) +} + +pub fn search_functions( + db: &cozo::DbInstance, + pattern: &str, + project: &str, + limit: u32, + use_regex: bool, +) -> Result, Box> { + let match_fn = if use_regex { "regex_matches" } else { "str_includes" }; + let script = format!( + r#" + ?[project, module, name, arity, return_type] := *functions{{project, module, name, arity, return_type}}, + project = $project, + {match_fn}(name, $pattern) + :limit {limit} + :order module, name, arity + "#, + ); + + let mut params = Params::new(); + params.insert("pattern".to_string(), DataValue::Str(pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| SearchError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 5 { + let Some(project) = extract_string(&row[0]) else { continue }; + let Some(module) = extract_string(&row[1]) else { continue }; + let Some(name) = extract_string(&row[2]) else { continue }; + let arity = extract_i64(&row[3], 0); + let return_type = extract_string_or(&row[4], ""); + results.push(FunctionResult { + project, + module, + name, + arity, + return_type, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/specs.rs b/db/src/queries/specs.rs new file mode 100644 index 0000000..fa64ee6 --- /dev/null +++ b/db/src/queries/specs.rs @@ -0,0 +1,127 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum SpecsError { + #[error("Specs query failed: {message}")] + QueryFailed { message: String }, +} + +/// A spec or callback definition +#[derive(Debug, Clone, Serialize)] +pub struct SpecDef { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub kind: String, + pub line: i64, + pub inputs_string: String, + pub return_string: String, + pub full: String, +} + +pub fn find_specs( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: Option<&str>, + kind_filter: Option<&str>, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + // Build module filter + let module_filter = if use_regex { + "regex_matches(module, $module_pattern)" + } else { + "module == $module_pattern" + }; + + // Build function filter + let function_filter = match function_pattern { + Some(_) if use_regex => ", regex_matches(name, $function_pattern)", + Some(_) => ", str_includes(name, $function_pattern)", + None => "", + }; + + // Build kind filter + let kind_filter_sql = match kind_filter { + Some(_) => ", kind == $kind", + None => "", + }; + + let script = format!( + r#" + ?[project, module, name, arity, kind, line, inputs_string, return_string, full] := + *specs{{project, module, name, arity, kind, line, inputs_string, return_string, full}}, + project == $project, + {module_filter} + {function_filter} + {kind_filter_sql} + + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert( + "module_pattern".to_string(), + DataValue::Str(module_pattern.into()), + ); + + if let Some(func) = function_pattern { + params.insert("function_pattern".to_string(), DataValue::Str(func.into())); + } + + if let Some(kind) = kind_filter { + params.insert("kind".to_string(), DataValue::Str(kind.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| SpecsError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 9 { + let Some(project) = extract_string(&row[0]) else { + continue; + }; + let Some(module) = extract_string(&row[1]) else { + continue; + }; + let Some(name) = extract_string(&row[2]) else { + continue; + }; + let arity = extract_i64(&row[3], 0); + let Some(kind) = extract_string(&row[4]) else { + continue; + }; + let line = extract_i64(&row[5], 0); + let inputs_string = extract_string(&row[6]).unwrap_or_default(); + let return_string = extract_string(&row[7]).unwrap_or_default(); + let full = extract_string(&row[8]).unwrap_or_default(); + + results.push(SpecDef { + project, + module, + name, + arity, + kind, + line, + inputs_string, + return_string, + full, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/struct_usage.rs b/db/src/queries/struct_usage.rs new file mode 100644 index 0000000..07b2b8e --- /dev/null +++ b/db/src/queries/struct_usage.rs @@ -0,0 +1,107 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum StructUsageError { + #[error("Struct usage query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function that accepts or returns a specific type +#[derive(Debug, Clone, Serialize)] +pub struct StructUsageEntry { + pub project: String, + pub module: String, + pub name: String, + pub arity: i64, + pub inputs_string: String, + pub return_string: String, + pub line: i64, +} + +pub fn find_struct_usage( + db: &cozo::DbInstance, + pattern: &str, + project: &str, + use_regex: bool, + module_pattern: Option<&str>, + limit: u32, +) -> Result, Box> { + // Build pattern matching function for both inputs and return + let match_fn = if use_regex { + "regex_matches(inputs_string, $pattern) or regex_matches(return_string, $pattern)" + } else { + "str_includes(inputs_string, $pattern) or str_includes(return_string, $pattern)" + }; + + // Build module filter + let module_filter = match module_pattern { + Some(_) if use_regex => "regex_matches(module, $module_pattern)", + Some(_) => "str_includes(module, $module_pattern)", + None => "true", + }; + + let script = format!( + r#" + ?[project, module, name, arity, inputs_string, return_string, line] := + *specs{{project, module, name, arity, inputs_string, return_string, line}}, + project == $project, + {match_fn}, + {module_filter} + + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("pattern".to_string(), DataValue::Str(pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + if let Some(mod_pat) = module_pattern { + params.insert( + "module_pattern".to_string(), + DataValue::Str(mod_pat.into()), + ); + } + + let rows = run_query(db, &script, params).map_err(|e| StructUsageError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 7 { + let Some(project) = extract_string(&row[0]) else { + continue; + }; + let Some(module) = extract_string(&row[1]) else { + continue; + }; + let Some(name) = extract_string(&row[2]) else { + continue; + }; + let arity = extract_i64(&row[3], 0); + let inputs_string = extract_string(&row[4]).unwrap_or_default(); + let return_string = extract_string(&row[5]).unwrap_or_default(); + let line = extract_i64(&row[6], 0); + + results.push(StructUsageEntry { + project, + module, + name, + arity, + inputs_string, + return_string, + line, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/structs.rs b/db/src/queries/structs.rs new file mode 100644 index 0000000..10686a5 --- /dev/null +++ b/db/src/queries/structs.rs @@ -0,0 +1,124 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_bool, extract_string, extract_string_or, run_query, Params}; + +#[derive(Error, Debug)] +pub enum StructError { + #[error("Struct query failed: {message}")] + QueryFailed { message: String }, +} + +/// A struct field definition +#[derive(Debug, Clone, Serialize)] +pub struct StructField { + pub project: String, + pub module: String, + pub field: String, + pub default_value: String, + pub required: bool, + pub inferred_type: String, +} + +/// A struct with all its fields grouped +#[derive(Debug, Clone, Serialize)] +pub struct StructDefinition { + pub project: String, + pub module: String, + pub fields: Vec, +} + +/// Field information within a struct +#[derive(Debug, Clone, Serialize)] +pub struct FieldInfo { + pub name: String, + pub default_value: String, + pub required: bool, + pub inferred_type: String, +} + +pub fn find_struct_fields( + db: &cozo::DbInstance, + module_pattern: &str, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + let module_cond = if use_regex { + "regex_matches(module, $module_pattern)".to_string() + } else { + "module == $module_pattern".to_string() + }; + + let project_cond = ", project == $project"; + + let script = format!( + r#" + ?[project, module, field, default_value, required, inferred_type] := + *struct_fields{{project, module, field, default_value, required, inferred_type}}, + {module_cond} + {project_cond} + :order module, field + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| StructError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(project) = extract_string(&row[0]) else { continue }; + let Some(module) = extract_string(&row[1]) else { continue }; + let Some(field) = extract_string(&row[2]) else { continue }; + let default_value = extract_string_or(&row[3], ""); + let required = extract_bool(&row[4], false); + let inferred_type = extract_string_or(&row[5], ""); + + results.push(StructField { + project, + module, + field, + default_value, + required, + inferred_type, + }); + } + } + + Ok(results) +} + +pub fn group_fields_into_structs(fields: Vec) -> Vec { + use std::collections::BTreeMap; + + let mut grouped: BTreeMap<(String, String), Vec> = BTreeMap::new(); + + for field in fields { + let key = (field.project.clone(), field.module.clone()); + grouped.entry(key).or_default().push(FieldInfo { + name: field.field, + default_value: field.default_value, + required: field.required, + inferred_type: field.inferred_type, + }); + } + + grouped + .into_iter() + .map(|((project, module), fields)| StructDefinition { + project, + module, + fields, + }) + .collect() +} diff --git a/db/src/queries/trace.rs b/db/src/queries/trace.rs new file mode 100644 index 0000000..83b6e7f --- /dev/null +++ b/db/src/queries/trace.rs @@ -0,0 +1,133 @@ +use std::error::Error; +use std::rc::Rc; + +use cozo::DataValue; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; +use crate::types::{Call, FunctionRef}; +use crate::query_builders::{ConditionBuilder, OptionalConditionBuilder}; + +#[derive(Error, Debug)] +pub enum TraceError { + #[error("Trace query failed: {message}")] + QueryFailed { message: String }, +} + +pub fn trace_calls( + db: &cozo::DbInstance, + module_pattern: &str, + function_pattern: &str, + arity: Option, + project: &str, + use_regex: bool, + max_depth: u32, + limit: u32, +) -> Result, Box> { + // Build the starting conditions for the recursive query using helpers + let module_cond = ConditionBuilder::new("caller_module", "module_pattern").build(use_regex); + let function_cond = ConditionBuilder::new("caller_name", "function_pattern").build(use_regex); + let arity_cond = OptionalConditionBuilder::new("caller_arity", "arity") + .when_none("true") + .build(arity.is_some()); + + // Recursive query to trace call chains, joined with function_locations for caller metadata + // Base case: direct calls from the starting function + // Recursive case: calls from functions we've already found + // Filter out struct calls (callee_function != '%') + let script = format!( + r#" + # Base case: calls from the starting function, joined with function_locations + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, + starts_with(caller_function, caller_name), + call_line >= caller_start_line, + call_line <= caller_end_line, + callee_function != '%', + {module_cond}, + {function_cond}, + project == $project, + {arity_cond}, + depth = 1 + + # Recursive case: calls from callees we've found + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + trace[prev_depth, _, _, _, _, _, _, prev_callee_module, prev_callee_function, _, _, _], + *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, + *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, + caller_module == prev_callee_module, + starts_with(caller_function, caller_name), + starts_with(caller_function, prev_callee_function), + call_line >= caller_start_line, + call_line <= caller_end_line, + callee_function != '%', + prev_depth < {max_depth}, + depth = prev_depth + 1, + project == $project + + ?[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := + trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] + + :order depth, caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); + params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); + if let Some(a) = arity { + params.insert("arity".to_string(), DataValue::from(a)); + } + params.insert("project".to_string(), DataValue::Str(project.into())); + + let rows = run_query(db, &script, params).map_err(|e| TraceError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 12 { + let depth = extract_i64(&row[0], 0); + let Some(caller_module) = extract_string(&row[1]) else { continue }; + let Some(caller_name) = extract_string(&row[2]) else { continue }; + let caller_arity = extract_i64(&row[3], 0); + let caller_kind = extract_string_or(&row[4], ""); + let caller_start_line = extract_i64(&row[5], 0); + let caller_end_line = extract_i64(&row[6], 0); + let Some(callee_module) = extract_string(&row[7]) else { continue }; + let Some(callee_name) = extract_string(&row[8]) else { continue }; + let callee_arity = extract_i64(&row[9], 0); + let Some(file) = extract_string(&row[10]) else { continue }; + let line = extract_i64(&row[11], 0); + + let caller = FunctionRef::with_definition( + Rc::from(caller_module.into_boxed_str()), + Rc::from(caller_name.into_boxed_str()), + caller_arity, + Rc::from(caller_kind.into_boxed_str()), + Rc::from(file.into_boxed_str()), + caller_start_line, + caller_end_line, + ); + + // Callee doesn't have definition info from this query + let callee = FunctionRef::new( + Rc::from(callee_module.into_boxed_str()), + Rc::from(callee_name.into_boxed_str()), + callee_arity, + ); + + results.push(Call { + caller, + callee, + line, + call_type: None, + depth: Some(depth), + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/types.rs b/db/src/queries/types.rs new file mode 100644 index 0000000..aa08274 --- /dev/null +++ b/db/src/queries/types.rs @@ -0,0 +1,121 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum TypesError { + #[error("Types query failed: {message}")] + QueryFailed { message: String }, +} + +/// A type definition (@type, @typep, @opaque) +#[derive(Debug, Clone, Serialize)] +pub struct TypeInfo { + pub project: String, + pub module: String, + pub name: String, + pub kind: String, + pub params: String, + pub line: i64, + pub definition: String, +} + +pub fn find_types( + db: &cozo::DbInstance, + module_pattern: &str, + name_filter: Option<&str>, + kind_filter: Option<&str>, + project: &str, + use_regex: bool, + limit: u32, +) -> Result, Box> { + // Build module filter + let module_filter = if use_regex { + "regex_matches(module, $module_pattern)" + } else { + "module == $module_pattern" + }; + + // Build name filter + let name_filter_sql = match name_filter { + Some(_) if use_regex => ", regex_matches(name, $name_pattern)", + Some(_) => ", str_includes(name, $name_pattern)", + None => "", + }; + + // Build kind filter + let kind_filter_sql = match kind_filter { + Some(_) => ", kind == $kind", + None => "", + }; + + let script = format!( + r#" + ?[project, module, name, kind, params, line, definition] := + *types{{project, module, name, kind, params, line, definition}}, + project == $project, + {module_filter} + {name_filter_sql} + {kind_filter_sql} + + :order module, name + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + params.insert( + "module_pattern".to_string(), + DataValue::Str(module_pattern.into()), + ); + + if let Some(name) = name_filter { + params.insert("name_pattern".to_string(), DataValue::Str(name.into())); + } + + if let Some(kind) = kind_filter { + params.insert("kind".to_string(), DataValue::Str(kind.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| TypesError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 7 { + let Some(project) = extract_string(&row[0]) else { + continue; + }; + let Some(module) = extract_string(&row[1]) else { + continue; + }; + let Some(name) = extract_string(&row[2]) else { + continue; + }; + let Some(kind) = extract_string(&row[3]) else { + continue; + }; + let params_str = extract_string(&row[4]).unwrap_or_default(); + let line = extract_i64(&row[5], 0); + let definition = extract_string(&row[6]).unwrap_or_default(); + + results.push(TypeInfo { + project, + module, + name, + kind, + params: params_str, + line, + definition, + }); + } + } + + Ok(results) +} diff --git a/db/src/queries/unused.rs b/db/src/queries/unused.rs new file mode 100644 index 0000000..070f534 --- /dev/null +++ b/db/src/queries/unused.rs @@ -0,0 +1,135 @@ +use std::error::Error; + +use cozo::DataValue; +use serde::Serialize; +use thiserror::Error; + +use crate::db::{extract_i64, extract_string, run_query, Params}; + +#[derive(Error, Debug)] +pub enum UnusedError { + #[error("Unused query failed: {message}")] + QueryFailed { message: String }, +} + +/// A function that is never called +#[derive(Debug, Clone, Serialize)] +pub struct UnusedFunction { + pub module: String, + pub name: String, + pub arity: i64, + pub kind: String, + pub file: String, + pub line: i64, +} + +/// Generated function name patterns to exclude (Elixir compiler-generated) +const GENERATED_PATTERNS: &[&str] = &[ + "__struct__", + "__using__", + "__before_compile__", + "__after_compile__", + "__on_definition__", + "__impl__", + "__info__", + "__protocol__", + "__deriving__", + "__changeset__", + "__schema__", + "__meta__", +]; + +pub fn find_unused_functions( + db: &cozo::DbInstance, + module_pattern: Option<&str>, + project: &str, + use_regex: bool, + private_only: bool, + public_only: bool, + exclude_generated: bool, + limit: u32, +) -> Result, Box> { + // Build optional module filter + let module_filter = match module_pattern { + Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), + Some(_) => ", str_includes(module, $module_pattern)".to_string(), + None => String::new(), + }; + + // Build kind filter for private_only/public_only + let kind_filter = if private_only { + ", (kind == \"defp\" or kind == \"defmacrop\")".to_string() + } else if public_only { + ", (kind == \"def\" or kind == \"defmacro\")".to_string() + } else { + String::new() + }; + + // Find functions that exist in function_locations but are never called + // We use function_locations as the source of "defined functions" and check + // if they appear as a callee in the calls table + let script = format!( + r#" + # All defined functions + defined[module, name, arity, kind, file, start_line] := + *function_locations{{project, module, name, arity, kind, file, start_line}}, + project == $project + {module_filter} + {kind_filter} + + # All functions that are called (as callees) + called[module, name, arity] := + *calls{{project, callee_module, callee_function, callee_arity}}, + project == $project, + module = callee_module, + name = callee_function, + arity = callee_arity + + # Functions that are defined but never called + ?[module, name, arity, kind, file, line] := + defined[module, name, arity, kind, file, line], + not called[module, name, arity] + + :order module, name, arity + :limit {limit} + "#, + ); + + let mut params = Params::new(); + params.insert("project".to_string(), DataValue::Str(project.into())); + if let Some(pattern) = module_pattern { + params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); + } + + let rows = run_query(db, &script, params).map_err(|e| UnusedError::QueryFailed { + message: e.to_string(), + })?; + + let mut results = Vec::new(); + for row in rows.rows { + if row.len() >= 6 { + let Some(module) = extract_string(&row[0]) else { continue }; + let Some(name) = extract_string(&row[1]) else { continue }; + let arity = extract_i64(&row[2], 0); + let Some(kind) = extract_string(&row[3]) else { continue }; + let Some(file) = extract_string(&row[4]) else { continue }; + let line = extract_i64(&row[5], 0); + + // Filter out generated functions if requested + if exclude_generated && GENERATED_PATTERNS.iter().any(|p| name.starts_with(p)) { + continue; + } + + results.push(UnusedFunction { + module, + name, + arity, + kind, + file, + line, + }); + } + } + + Ok(results) +} From 32c617269f71390c3069ad2ae1eafb94a14bb988 Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Mon, 22 Dec 2025 23:52:53 +0100 Subject: [PATCH 5/8] Move test infrastructure to db crate with test-utils feature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ticket 5 of 8 - Move test infrastructure. Changes: - Copy all fixtures to db/src/fixtures/ - call_graph.json, type_signatures.json, structs.json - output/ directory with all command output fixtures - extracted_trace.json for large trace tests - Copy and modify test_utils.rs to db/src/test_utils.rs - Remove Execute-dependent functions (execute_cmd, execute_on_empty_db) - Keep db-specific helpers (setup_test_db, create_temp_json_file, etc.) - Add #![cfg(feature = "test-utils")] feature gate - Update db/src/lib.rs with feature-gated test modules - Update db/Cargo.toml: - Add tempfile and serde_json as optional dependencies - Define test-utils feature - Update db.rs and import.rs to conditionally export test functions Functions available in test-utils feature: - create_temp_json_file() - Create temporary JSON for testing - setup_test_db() - Set up test database with fixture data - setup_empty_test_db() - Create empty database for error testing - call_graph_db(), type_signatures_db(), structs_db() - Pre-configured DBs - load_output_fixture() - Load expected output for validation Verification: - cargo test -p db: ✅ 37 tests pass - cargo build -p db --features test-utils: ✅ compiles The db crate is now complete with all core functionality and test infrastructure. CLI crate can use test helpers via: db = { path = "../db", features = ["test-utils"] } Relates to ticket: scratch/tickets/05-test-infrastructure.md --- db/Cargo.toml | 4 +- db/src/db.rs | 2 +- db/src/fixtures/call_graph.json | 468 + db/src/fixtures/extracted_trace.json | 53152 ++++++++++++++++ db/src/fixtures/mod.rs | 74 + db/src/fixtures/output/calls_from/empty.toon | 4 + db/src/fixtures/output/calls_from/single.json | 40 + db/src/fixtures/output/calls_from/single.toon | 27 + db/src/fixtures/output/calls_to/empty.toon | 4 + db/src/fixtures/output/calls_to/single.json | 36 + db/src/fixtures/output/calls_to/single.toon | 23 + db/src/fixtures/output/depended_by/empty.toon | 3 + .../fixtures/output/depended_by/single.json | 26 + .../fixtures/output/depended_by/single.toon | 13 + db/src/fixtures/output/depends_on/empty.toon | 3 + db/src/fixtures/output/depends_on/single.json | 34 + db/src/fixtures/output/depends_on/single.toon | 21 + db/src/fixtures/output/function/empty.toon | 4 + db/src/fixtures/output/function/single.json | 18 + db/src/fixtures/output/function/single.toon | 7 + db/src/fixtures/output/hotspots/empty.toon | 4 + db/src/fixtures/output/hotspots/single.json | 19 + db/src/fixtures/output/hotspots/single.toon | 7 + db/src/fixtures/output/import/full.json | 19 + db/src/fixtures/output/import/full.toon | 11 + db/src/fixtures/output/location/empty.toon | 4 + db/src/fixtures/output/location/single.json | 25 + db/src/fixtures/output/location/single.toon | 12 + db/src/fixtures/output/path/empty.toon | 6 + db/src/fixtures/output/path/single.json | 33 + db/src/fixtures/output/path/single.toon | 9 + .../fixtures/output/reverse_trace/empty.toon | 5 + .../fixtures/output/reverse_trace/single.json | 25 + .../fixtures/output/reverse_trace/single.toon | 14 + db/src/fixtures/output/search/empty.toon | 2 + db/src/fixtures/output/search/modules.json | 16 + db/src/fixtures/output/search/modules.toon | 5 + db/src/fixtures/output/trace/empty.toon | 5 + db/src/fixtures/output/trace/single.json | 25 + db/src/fixtures/output/trace/single.toon | 14 + db/src/fixtures/output/unused/empty.toon | 3 + db/src/fixtures/output/unused/single.json | 18 + db/src/fixtures/output/unused/single.toon | 7 + db/src/fixtures/structs.json | 33 + db/src/fixtures/type_signatures.json | 176 + db/src/lib.rs | 8 +- db/src/queries/import.rs | 2 +- db/src/test_utils.rs | 94 + 48 files changed, 54560 insertions(+), 4 deletions(-) create mode 100644 db/src/fixtures/call_graph.json create mode 100644 db/src/fixtures/extracted_trace.json create mode 100644 db/src/fixtures/mod.rs create mode 100644 db/src/fixtures/output/calls_from/empty.toon create mode 100644 db/src/fixtures/output/calls_from/single.json create mode 100644 db/src/fixtures/output/calls_from/single.toon create mode 100644 db/src/fixtures/output/calls_to/empty.toon create mode 100644 db/src/fixtures/output/calls_to/single.json create mode 100644 db/src/fixtures/output/calls_to/single.toon create mode 100644 db/src/fixtures/output/depended_by/empty.toon create mode 100644 db/src/fixtures/output/depended_by/single.json create mode 100644 db/src/fixtures/output/depended_by/single.toon create mode 100644 db/src/fixtures/output/depends_on/empty.toon create mode 100644 db/src/fixtures/output/depends_on/single.json create mode 100644 db/src/fixtures/output/depends_on/single.toon create mode 100644 db/src/fixtures/output/function/empty.toon create mode 100644 db/src/fixtures/output/function/single.json create mode 100644 db/src/fixtures/output/function/single.toon create mode 100644 db/src/fixtures/output/hotspots/empty.toon create mode 100644 db/src/fixtures/output/hotspots/single.json create mode 100644 db/src/fixtures/output/hotspots/single.toon create mode 100644 db/src/fixtures/output/import/full.json create mode 100644 db/src/fixtures/output/import/full.toon create mode 100644 db/src/fixtures/output/location/empty.toon create mode 100644 db/src/fixtures/output/location/single.json create mode 100644 db/src/fixtures/output/location/single.toon create mode 100644 db/src/fixtures/output/path/empty.toon create mode 100644 db/src/fixtures/output/path/single.json create mode 100644 db/src/fixtures/output/path/single.toon create mode 100644 db/src/fixtures/output/reverse_trace/empty.toon create mode 100644 db/src/fixtures/output/reverse_trace/single.json create mode 100644 db/src/fixtures/output/reverse_trace/single.toon create mode 100644 db/src/fixtures/output/search/empty.toon create mode 100644 db/src/fixtures/output/search/modules.json create mode 100644 db/src/fixtures/output/search/modules.toon create mode 100644 db/src/fixtures/output/trace/empty.toon create mode 100644 db/src/fixtures/output/trace/single.json create mode 100644 db/src/fixtures/output/trace/single.toon create mode 100644 db/src/fixtures/output/unused/empty.toon create mode 100644 db/src/fixtures/output/unused/single.json create mode 100644 db/src/fixtures/output/unused/single.toon create mode 100644 db/src/fixtures/structs.json create mode 100644 db/src/fixtures/type_signatures.json create mode 100644 db/src/test_utils.rs diff --git a/db/Cargo.toml b/db/Cargo.toml index 3129629..9f4c604 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -10,6 +10,8 @@ thiserror = "1.0" regex = "1" include_dir = "0.7" clap = { version = "4", features = ["derive"] } +tempfile = { version = "3", optional = true } +serde_json = { version = "1.0", optional = true } [dev-dependencies] rstest = "0.23" @@ -17,4 +19,4 @@ tempfile = "3" serde_json = "1.0" [features] -test-utils = [] +test-utils = ["tempfile", "serde_json"] diff --git a/db/src/db.rs b/db/src/db.rs index e74370d..7958958 100644 --- a/db/src/db.rs +++ b/db/src/db.rs @@ -64,7 +64,7 @@ pub fn open_db(path: &Path) -> Result> { /// Create an in-memory database instance. /// /// Used for tests to avoid disk I/O and temp file management. -#[cfg(test)] +#[cfg(any(test, feature = "test-utils"))] pub fn open_mem_db() -> DbInstance { DbInstance::new("mem", "", "").expect("Failed to create in-memory DB") } diff --git a/db/src/fixtures/call_graph.json b/db/src/fixtures/call_graph.json new file mode 100644 index 0000000..981814f --- /dev/null +++ b/db/src/fixtures/call_graph.json @@ -0,0 +1,468 @@ +{ + "structs": {}, + "function_locations": { + "MyApp.Controller": { + "index/2:5": { + "file": "lib/my_app/controller.ex", + "column": 3, + "kind": "def", + "line": 5, + "start_line": 5, + "end_line": 10, + "pattern": "conn, params", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "index", + "arity": 2 + }, + "show/2:12": { + "file": "lib/my_app/controller.ex", + "column": 3, + "kind": "def", + "line": 12, + "start_line": 12, + "end_line": 18, + "pattern": "conn, params", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "show", + "arity": 2 + }, + "create/2:20": { + "file": "lib/my_app/controller.ex", + "column": 3, + "kind": "def", + "line": 20, + "start_line": 20, + "end_line": 30, + "pattern": "conn, params", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "create", + "arity": 2 + } + }, + "MyApp.Accounts": { + "get_user/1:10": { + "file": "lib/my_app/accounts.ex", + "column": 3, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15, + "pattern": "id", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "get_user", + "arity": 1 + }, + "get_user/2:17": { + "file": "lib/my_app/accounts.ex", + "column": 3, + "kind": "def", + "line": 17, + "start_line": 17, + "end_line": 22, + "pattern": "id, opts", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "get_user", + "arity": 2 + }, + "list_users/0:24": { + "file": "lib/my_app/accounts.ex", + "column": 3, + "kind": "def", + "line": 24, + "start_line": 24, + "end_line": 28, + "pattern": "", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "list_users", + "arity": 0 + }, + "validate_email/1:30": { + "file": "lib/my_app/accounts.ex", + "column": 3, + "kind": "defp", + "line": 30, + "start_line": 30, + "end_line": 35, + "pattern": "email", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "validate_email", + "arity": 1 + } + }, + "MyApp.Service": { + "process/1:5": { + "file": "lib/my_app/service.ex", + "column": 3, + "kind": "def", + "line": 5, + "start_line": 5, + "end_line": 15, + "pattern": "data", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "process", + "arity": 1 + }, + "fetch/1:17": { + "file": "lib/my_app/service.ex", + "column": 3, + "kind": "def", + "line": 17, + "start_line": 17, + "end_line": 25, + "pattern": "id", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "fetch", + "arity": 1 + }, + "do_fetch/2:27": { + "file": "lib/my_app/service.ex", + "column": 3, + "kind": "defp", + "line": 27, + "start_line": 27, + "end_line": 35, + "pattern": "id, opts", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "do_fetch", + "arity": 2 + } + }, + "MyApp.Repo": { + "get/2:10": { + "file": "lib/my_app/repo.ex", + "column": 3, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15, + "pattern": "schema, id", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "get", + "arity": 2 + }, + "all/1:17": { + "file": "lib/my_app/repo.ex", + "column": 3, + "kind": "def", + "line": 17, + "start_line": 17, + "end_line": 22, + "pattern": "query", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "all", + "arity": 1 + }, + "insert/2:24": { + "file": "lib/my_app/repo.ex", + "column": 3, + "kind": "def", + "line": 24, + "start_line": 24, + "end_line": 30, + "pattern": "struct, opts", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "insert", + "arity": 2 + } + }, + "MyApp.Notifier": { + "notify/1:5": { + "file": "lib/my_app/notifier.ex", + "column": 3, + "kind": "def", + "line": 5, + "start_line": 5, + "end_line": 12, + "pattern": "user", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "notify", + "arity": 1 + }, + "send_email/2:14": { + "file": "lib/my_app/notifier.ex", + "column": 3, + "kind": "defp", + "line": 14, + "start_line": 14, + "end_line": 20, + "pattern": "to, body", + "guard": null, + "source_sha": "", + "ast_sha": "", + "name": "send_email", + "arity": 2 + } + } + }, + "calls": [ + { + "caller": { + "module": "MyApp.Controller", + "function": "index", + "file": "lib/my_app/controller.ex", + "line": 7, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 0, + "function": "list_users", + "module": "MyApp.Accounts" + } + }, + { + "caller": { + "module": "MyApp.Controller", + "function": "show", + "file": "lib/my_app/controller.ex", + "line": 14, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 1, + "function": "get_user", + "module": "MyApp.Accounts" + } + }, + { + "caller": { + "module": "MyApp.Controller", + "function": "create", + "file": "lib/my_app/controller.ex", + "line": 22, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 1, + "function": "process", + "module": "MyApp.Service" + } + }, + { + "caller": { + "module": "MyApp.Accounts", + "function": "get_user", + "file": "lib/my_app/accounts.ex", + "line": 12, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 2, + "function": "get", + "module": "MyApp.Repo" + } + }, + { + "caller": { + "module": "MyApp.Accounts", + "function": "get_user", + "file": "lib/my_app/accounts.ex", + "line": 19, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 2, + "function": "get", + "module": "MyApp.Repo" + } + }, + { + "caller": { + "module": "MyApp.Accounts", + "function": "list_users", + "file": "lib/my_app/accounts.ex", + "line": 26, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 1, + "function": "all", + "module": "MyApp.Repo" + } + }, + { + "caller": { + "module": "MyApp.Service", + "function": "process", + "file": "lib/my_app/service.ex", + "line": 8, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 1, + "function": "fetch", + "module": "MyApp.Service" + } + }, + { + "caller": { + "module": "MyApp.Service", + "function": "fetch", + "file": "lib/my_app/service.ex", + "line": 20, + "column": 5 + }, + "type": "local", + "callee": { + "arity": 2, + "function": "do_fetch", + "module": "MyApp.Service" + } + }, + { + "caller": { + "module": "MyApp.Service", + "function": "do_fetch", + "file": "lib/my_app/service.ex", + "line": 30, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 2, + "function": "get", + "module": "MyApp.Repo" + } + }, + { + "caller": { + "module": "MyApp.Service", + "function": "process", + "file": "lib/my_app/service.ex", + "line": 12, + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 1, + "function": "notify", + "module": "MyApp.Notifier" + } + }, + { + "caller": { + "module": "MyApp.Notifier", + "function": "notify", + "file": "lib/my_app/notifier.ex", + "line": 8, + "column": 5 + }, + "type": "local", + "callee": { + "arity": 2, + "function": "send_email", + "module": "MyApp.Notifier" + } + } + ], + "specs": { + "MyApp.Accounts": [ + { + "name": "get_user", + "arity": 1, + "kind": "spec", + "line": 8, + "clauses": [ + { + "full": "@spec get_user(integer()) :: {:ok, User.t()} | {:error, :not_found}", + "input_strings": [ + "integer()" + ], + "return_strings": [ + "{:ok, User.t()}", + "{:error, :not_found}" + ] + } + ] + }, + { + "name": "list_users", + "arity": 0, + "kind": "spec", + "line": 22, + "clauses": [ + { + "full": "@spec list_users() :: [User.t()]", + "input_strings": [], + "return_strings": [ + "[User.t()]" + ] + } + ] + } + ], + "MyApp.Repo": [ + { + "name": "get", + "arity": 2, + "kind": "callback", + "line": 8, + "clauses": [ + { + "full": "@callback get(module(), term()) :: Ecto.Schema.t() | nil", + "input_strings": [ + "module()", + "term()" + ], + "return_strings": [ + "Ecto.Schema.t()", + "nil" + ] + } + ] + } + ] + }, + "types": { + "MyApp.Accounts": [ + { + "name": "user", + "kind": "type", + "line": 5, + "params": [], + "definition": "@type user() :: %{id: integer(), name: String.t()}" + }, + { + "name": "user_id", + "kind": "opaque", + "line": 3, + "params": [], + "definition": "@opaque user_id() :: integer()" + } + ] + } +} diff --git a/db/src/fixtures/extracted_trace.json b/db/src/fixtures/extracted_trace.json new file mode 100644 index 0000000..472515d --- /dev/null +++ b/db/src/fixtures/extracted_trace.json @@ -0,0 +1,53152 @@ +{ + "specs": { + "Phoenix.Logger": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Notifier": [ + { + "arity": 1, + "line": 140, + "name": "raise_with_help", + "clauses": [ + { + "full": "@spec raise_with_help(String.t()) :: no_return()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 181, + "name": "maybe_print_mailer_installation_instructions", + "clauses": [ + { + "full": "@spec maybe_print_mailer_installation_instructions(%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}) :: %{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}", + "input_strings": [ + "%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}" + ], + "return_strings": [ + "%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Channel": [ + { + "arity": 2, + "line": 436, + "name": "terminate", + "clauses": [ + { + "full": "@callback terminate(:normal | :shutdown | {:shutdown, :left | :closed | term()}, Phoenix.Socket.t()) :: term()", + "input_strings": [ + ":normal | :shutdown | {:shutdown, :left | :closed | term()}", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 364, + "name": "join", + "clauses": [ + { + "full": "@callback join(binary(), payload(), Phoenix.Socket.t()) :: {:ok, Phoenix.Socket.t()} | {:ok, payload(), Phoenix.Socket.t()} | {:error, map()}", + "input_strings": [ + "binary()", + "payload()", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:ok, Phoenix.Socket.t()}", + "{:ok, payload(), Phoenix.Socket.t()}", + "{:error, map()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 392, + "name": "handle_out", + "clauses": [ + { + "full": "@callback handle_out(String.t(), payload(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t(), timeout() | :hibernate} | {:stop, term(), Phoenix.Socket.t()}", + "input_strings": [ + "String.t()", + "payload()", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:noreply, Phoenix.Socket.t()}", + "{:noreply, Phoenix.Socket.t(), timeout()", + ":hibernate}", + "{:stop, term(), Phoenix.Socket.t()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 402, + "name": "handle_info", + "clauses": [ + { + "full": "@callback handle_info(term(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", + "input_strings": [ + "term()", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:noreply, Phoenix.Socket.t()}", + "{:stop, term(), Phoenix.Socket.t()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 380, + "name": "handle_in", + "clauses": [ + { + "full": "@callback handle_in(String.t(), payload(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t(), timeout() | :hibernate} | {:reply, reply(), Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()} | {:stop, term(), reply(), Phoenix.Socket.t()}", + "input_strings": [ + "String.t()", + "payload()", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:noreply, Phoenix.Socket.t()}", + "{:noreply, Phoenix.Socket.t(), timeout()", + ":hibernate}", + "{:reply, reply(), Phoenix.Socket.t()}", + "{:stop, term(), Phoenix.Socket.t()}", + "{:stop, term(), reply(), Phoenix.Socket.t()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 421, + "name": "handle_cast", + "clauses": [ + { + "full": "@callback handle_cast(term(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", + "input_strings": [ + "term()", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:noreply, Phoenix.Socket.t()}", + "{:stop, term(), Phoenix.Socket.t()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 411, + "name": "handle_call", + "clauses": [ + { + "full": "@callback handle_call(term(), {pid(), term()}, Phoenix.Socket.t()) :: {:reply, term(), Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", + "input_strings": [ + "term()", + "{pid(), term()}", + "Phoenix.Socket.t()" + ], + "return_strings": [ + "{:reply, term(), Phoenix.Socket.t()}", + "{:noreply, Phoenix.Socket.t()}", + "{:stop, term(), Phoenix.Socket.t()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 426, + "name": "code_change", + "clauses": [ + { + "full": "@callback code_change(old_vsn, Phoenix.Socket.t(), term()) :: {:ok, Phoenix.Socket.t()} | {:error, term()}", + "input_strings": [ + "old_vsn", + "Phoenix.Socket.t()", + "term()" + ], + "return_strings": [ + "{:ok, Phoenix.Socket.t()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 687, + "name": "socket_ref", + "clauses": [ + { + "full": "@spec socket_ref(Phoenix.Socket.t()) :: socket_ref()", + "input_strings": [ + "Phoenix.Socket.t()" + ], + "return_strings": [ + "socket_ref()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 673, + "name": "reply", + "clauses": [ + { + "full": "@spec reply(socket_ref(), reply()) :: :ok", + "input_strings": [ + "socket_ref()", + "reply()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Channel.Server": [ + { + "arity": 1, + "line": 65, + "name": "socket", + "clauses": [ + { + "full": "@spec socket(pid()) :: Phoenix.Socket.t()", + "input_strings": [ + "pid()" + ], + "return_strings": [ + "Phoenix.Socket.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 4, + "line": 16, + "name": "join", + "clauses": [ + { + "full": "@spec join(Phoenix.Socket.t(), module(), Phoenix.Socket.Message.t(), elixir.keyword()) :: {:ok, term(), pid()} | {:error, term()}", + "input_strings": [ + "Phoenix.Socket.t()", + "module()", + "Phoenix.Socket.Message.t()", + "elixir.keyword()" + ], + "return_strings": [ + "{:ok, term(), pid()}", + "{:error, term()}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 75, + "name": "close", + "clauses": [ + { + "full": "@spec close(pid(), timeout()) :: :ok", + "input_strings": [ + "pid()", + "timeout()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.PoolDrainer": [ + { + "arity": 1, + "line": 66, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Controller": [ + { + "arity": 1, + "line": 346, + "name": "view_template", + "clauses": [ + { + "full": "@spec view_template(Plug.Conn.t()) :: binary() | nil", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "binary()", + "nil" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 602, + "name": "view_module", + "clauses": [ + { + "full": "@spec view_module(Plug.Conn.t(), binary() | nil) :: atom()", + "input_strings": [ + "Plug.Conn.t()", + "binary() | nil" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 454, + "name": "text", + "clauses": [ + { + "full": "@spec text(Plug.Conn.t(), String.Chars.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "String.Chars.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 1333, + "name": "scrub_params", + "clauses": [ + { + "full": "@spec scrub_params(Plug.Conn.t(), String.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "String.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 333, + "name": "router_module", + "clauses": [ + { + "full": "@spec router_module(Plug.Conn.t()) :: atom()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 847, + "name": "root_layout", + "clauses": [ + { + "full": "@spec root_layout(Plug.Conn.t(), binary() | nil) :: {atom(), String.t() | atom()} | false", + "input_strings": [ + "Plug.Conn.t()", + "binary() | nil" + ], + "return_strings": [ + "{atom(), String.t()", + "atom()}", + "false" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 943, + "name": "render", + "clauses": [ + { + "full": "@spec render(Plug.Conn.t(), binary() | atom(), Keyword.t() | map()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "binary() | atom()", + "Keyword.t() | map()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 869, + "name": "render", + "clauses": [ + { + "full": "@spec render(Plug.Conn.t(), Keyword.t() | map() | binary() | atom()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "Keyword.t() | map() | binary() | atom()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 1618, + "name": "refuse", + "clauses": [ + { + "full": "@spec refuse(term(), [tuple()], [binary()]) :: no_return()", + "input_strings": [ + "term()", + "[tuple()]", + "[binary()]" + ], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 520, + "name": "raise_invalid_url", + "clauses": [ + { + "full": "@spec raise_invalid_url(term()) :: no_return()", + "input_strings": [ + "term()" + ], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 535, + "name": "put_view", + "clauses": [ + { + "full": "@spec put_view(Plug.Conn.t(), [{atom(), view()}] | view()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[{atom(), view()}] | view()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 790, + "name": "put_root_layout", + "clauses": [ + { + "full": "@spec put_root_layout(Plug.Conn.t(), [{atom(), layout()}] | false) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[{atom(), layout()}] | false" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 581, + "name": "put_new_view", + "clauses": [ + { + "full": "@spec put_new_view(Plug.Conn.t(), [{atom(), view()}] | view()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[{atom(), view()}] | view()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 742, + "name": "put_new_layout", + "clauses": [ + { + "full": "@spec put_new_layout(Plug.Conn.t(), [{atom(), layout()}] | layout()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[{atom(), layout()}] | layout()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 809, + "name": "put_layout_formats", + "clauses": [ + { + "full": "@spec put_layout_formats(Plug.Conn.t(), [String.t()]) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[String.t()]" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 649, + "name": "put_layout", + "clauses": [ + { + "full": "@spec put_layout(Plug.Conn.t(), [{atom(), layout()}] | false) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[{atom(), layout()}] | false" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 827, + "name": "layout_formats", + "clauses": [ + { + "full": "@spec layout_formats(Plug.Conn.t()) :: [String.t()]", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "[String.t()]" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 837, + "name": "layout", + "clauses": [ + { + "full": "@spec layout(Plug.Conn.t(), binary() | nil) :: {atom(), String.t() | atom()} | false", + "input_strings": [ + "Plug.Conn.t()", + "binary() | nil" + ], + "return_strings": [ + "{atom(), String.t()", + "atom()}", + "false" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 362, + "name": "json", + "clauses": [ + { + "full": "@spec json(Plug.Conn.t(), term()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "term()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 467, + "name": "html", + "clauses": [ + { + "full": "@spec html(Plug.Conn.t(), iodata()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "iodata()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 339, + "name": "endpoint_module", + "clauses": [ + { + "full": "@spec endpoint_module(Plug.Conn.t()) :: atom()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 327, + "name": "controller_module", + "clauses": [ + { + "full": "@spec controller_module(Plug.Conn.t()) :: atom()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 391, + "name": "allow_jsonp", + "clauses": [ + { + "full": "@spec allow_jsonp(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "Keyword.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 321, + "name": "action_name", + "clauses": [ + { + "full": "@spec action_name(Plug.Conn.t()) :: atom()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 1520, + "name": "accepts", + "clauses": [ + { + "full": "@spec accepts(Plug.Conn.t(), [binary()]) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[binary()]" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.Float": [ + { + "arity": 1, + "line": 70, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Float", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Float" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 70, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint.Watcher": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Socket": [ + { + "arity": 0, + "line": 81, + "name": "raise_with_help", + "clauses": [ + { + "full": "@spec raise_with_help() :: no_return()", + "input_strings": [], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.NoRouteError": [ + { + "arity": 1, + "line": 2, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.Helpers": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.CodeReloader.Proxy": [ + { + "arity": 1, + "line": 3, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.ActionClauseError": [ + { + "arity": 1, + "line": 41, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket": [ + { + "arity": 1, + "line": 246, + "name": "id", + "clauses": [ + { + "full": "@callback id(t()) :: String.t() | nil", + "input_strings": [ + "t()" + ], + "return_strings": [ + "String.t()", + "nil" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 222, + "name": "connect", + "clauses": [ + { + "full": "@callback connect(map(), t(), map()) :: {:ok, t()} | {:error, term()} | :error", + "input_strings": [ + "map()", + "t()", + "map()" + ], + "return_strings": [ + "{:ok, t()}", + "{:error, term()}", + ":error" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 230, + "name": "connect", + "clauses": [ + { + "full": "@callback connect(map(), t()) :: {:ok, t()} | {:error, term()} | :error", + "input_strings": [ + "map()", + "t()" + ], + "return_strings": [ + "{:ok, t()}", + "{:error, term()}", + ":error" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Digester.Gzip": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Channel": [ + { + "arity": 0, + "line": 96, + "name": "raise_with_help", + "clauses": [ + { + "full": "@spec raise_with_help() :: no_return()", + "input_strings": [], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.Transport": [ + { + "arity": 2, + "line": 245, + "name": "terminate", + "clauses": [ + { + "full": "@callback terminate(term(), state()) :: :ok", + "input_strings": [ + "term()", + "state()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 174, + "name": "init", + "clauses": [ + { + "full": "@callback init(state()) :: {:ok, state()}", + "input_strings": [ + "state()" + ], + "return_strings": [ + "{:ok, state()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 233, + "name": "handle_info", + "clauses": [ + { + "full": "@callback handle_info(term(), state()) :: {:ok, state()} | {:push, {atom(), term()}, state()} | {:stop, term(), state()}", + "input_strings": [ + "term()", + "state()" + ], + "return_strings": [ + "{:ok, state()}", + "{:push, {atom(), term()}, state()}", + "{:stop, term(), state()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 191, + "name": "handle_in", + "clauses": [ + { + "full": "@callback handle_in({term(), elixir.keyword()}, state()) :: {:ok, state()} | {:reply, :ok | :error, {atom(), term()}, state()} | {:stop, term(), state()}", + "input_strings": [ + "{term(), elixir.keyword()}", + "state()" + ], + "return_strings": [ + "{:ok, state()}", + "{:reply, :ok", + ":error, {atom(), term()}, state()}", + "{:stop, term(), state()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 214, + "name": "handle_control", + "clauses": [ + { + "full": "@callback handle_control({term(), elixir.keyword()}, state()) :: {:ok, state()} | {:reply, :ok | :error, {atom(), term()}, state()} | {:stop, term(), state()}", + "input_strings": [ + "{term(), elixir.keyword()}", + "state()" + ], + "return_strings": [ + "{:ok, state()}", + "{:reply, :ok", + ":error, {atom(), term()}, state()}", + "{:stop, term(), state()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 137, + "name": "drainer_spec", + "clauses": [ + { + "full": "@callback drainer_spec(elixir.keyword()) :: supervisor.child_spec() | :ignore", + "input_strings": [ + "elixir.keyword()" + ], + "return_strings": [ + "supervisor.child_spec()", + ":ignore" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 166, + "name": "connect", + "clauses": [ + { + "full": "@callback connect(map()) :: {:ok, state()} | {:error, term()} | :error", + "input_strings": [ + "map()" + ], + "return_strings": [ + "{:ok, state()}", + "{:error, term()}", + ":error" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 125, + "name": "child_spec", + "clauses": [ + { + "full": "@callback child_spec(elixir.keyword()) :: supervisor.child_spec() | :ignore", + "input_strings": [ + "elixir.keyword()" + ], + "return_strings": [ + "supervisor.child_spec()", + ":ignore" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Naming": [ + { + "arity": 2, + "line": 40, + "name": "unsuffix", + "clauses": [ + { + "full": "@spec unsuffix(String.t(), String.t()) :: String.t()", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 66, + "name": "underscore", + "clauses": [ + { + "full": "@spec underscore(String.t()) :: String.t()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 18, + "name": "resource_name", + "clauses": [ + { + "full": "@spec resource_name(String.Chars.t(), String.t()) :: String.t()", + "input_strings": [ + "String.Chars.t()", + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 119, + "name": "humanize", + "clauses": [ + { + "full": "@spec humanize(atom() | String.t()) :: String.t()", + "input_strings": [ + "atom() | String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 96, + "name": "camelize", + "clauses": [ + { + "full": "@spec camelize(String.t(), :lower) :: String.t()", + "input_strings": [ + "String.t()", + ":lower" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 93, + "name": "camelize", + "clauses": [ + { + "full": "@spec camelize(String.t()) :: String.t()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Flash": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param": [ + { + "arity": 1, + "line": 62, + "name": "to_param", + "clauses": [ + { + "full": "@callback to_param(term()) :: String.t()", + "input_strings": [ + "term()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 62, + "name": "to_param", + "clauses": [ + { + "full": "@spec to_param(term()) :: String.t()", + "input_strings": [ + "term()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "impl_for!", + "clauses": [ + { + "full": "@spec impl_for!(term()) :: atom()", + "input_strings": [ + "term()" + ], + "return_strings": [ + "atom()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "impl_for", + "clauses": [ + { + "full": "@spec impl_for(term()) :: atom() | nil", + "input_strings": [ + "term()" + ], + "return_strings": [ + "atom()", + "nil" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__protocol__", + "clauses": [ + { + "full": "@spec __protocol__(:module) :: Phoenix.Param", + "input_strings": [ + ":module" + ], + "return_strings": [ + "Phoenix.Param" + ] + }, + { + "full": "@spec __protocol__(:functions) :: [{atom(), arity()}]", + "input_strings": [ + ":functions" + ], + "return_strings": [ + "[{atom(), arity()}]" + ] + }, + { + "full": "@spec __protocol__(:consolidated?) :: boolean()", + "input_strings": [ + ":consolidated?" + ], + "return_strings": [ + "boolean()" + ] + }, + { + "full": "@spec __protocol__(:impls) :: :not_consolidated | {:consolidated, [module()]}", + "input_strings": [ + ":impls" + ], + "return_strings": [ + ":not_consolidated", + "{:consolidated, [module()]}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Embedded": [ + { + "arity": 1, + "line": 80, + "name": "raise_with_help", + "clauses": [ + { + "full": "@spec raise_with_help(String.t()) :: no_return()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Schema": [ + { + "arity": 1, + "line": 276, + "name": "raise_with_help", + "clauses": [ + { + "full": "@spec raise_with_help(String.t()) :: no_return()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.Serializer": [ + { + "arity": 1, + "line": 14, + "name": "fastlane!", + "clauses": [ + { + "full": "@callback fastlane!(Phoenix.Socket.Broadcast.t()) :: {:socket_push, :text, iodata()} | {:socket_push, :binary, iodata()}", + "input_strings": [ + "Phoenix.Socket.Broadcast.t()" + ], + "return_strings": [ + "{:socket_push, :text, iodata()}", + "{:socket_push, :binary, iodata()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 21, + "name": "encode!", + "clauses": [ + { + "full": "@callback encode!(Phoenix.Socket.Message.t() | Phoenix.Socket.Reply.t()) :: {:socket_push, :text, iodata()} | {:socket_push, :binary, iodata()}", + "input_strings": [ + "Phoenix.Socket.Message.t() | Phoenix.Socket.Reply.t()" + ], + "return_strings": [ + "{:socket_push, :text, iodata()}", + "{:socket_push, :binary, iodata()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 28, + "name": "decode!", + "clauses": [ + { + "full": "@callback decode!(iodata(), Keyword.t()) :: Phoenix.Socket.Message.t()", + "input_strings": [ + "iodata()", + "Keyword.t()" + ], + "return_strings": [ + "Phoenix.Socket.Message.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Digest": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Html": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.Integer": [ + { + "arity": 1, + "line": 66, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Integer", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Integer" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 66, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint": [ + { + "arity": 0, + "line": 313, + "name": "url", + "clauses": [ + { + "full": "@callback url() :: String.t()", + "input_strings": [], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 371, + "name": "unsubscribe", + "clauses": [ + { + "full": "@callback unsubscribe(topic()) :: :ok | {:error, term()}", + "input_strings": [ + "topic()" + ], + "return_strings": [ + ":ok", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 366, + "name": "subscribe", + "clauses": [ + { + "full": "@callback subscribe(topic(), Keyword.t()) :: :ok | {:error, term()}", + "input_strings": [ + "topic()", + "Keyword.t()" + ], + "return_strings": [ + ":ok", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 0, + "line": 308, + "name": "struct_url", + "clauses": [ + { + "full": "@callback struct_url() :: URI.t()", + "input_strings": [], + "return_strings": [ + "URI.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 0, + "line": 323, + "name": "static_url", + "clauses": [ + { + "full": "@callback static_url() :: String.t()", + "input_strings": [], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 328, + "name": "static_path", + "clauses": [ + { + "full": "@callback static_path(String.t()) :: String.t()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 338, + "name": "static_lookup", + "clauses": [ + { + "full": "@callback static_lookup(String.t()) :: {String.t(), String.t()} | {String.t(), nil}", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "{String.t(), String.t()}", + "{String.t(), nil}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 333, + "name": "static_integrity", + "clauses": [ + { + "full": "@callback static_integrity(String.t()) :: String.t() | nil", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()", + "nil" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 291, + "name": "start_link", + "clauses": [ + { + "full": "@callback start_link(elixir.keyword()) :: Supervisor.on_start()", + "input_strings": [ + "elixir.keyword()" + ], + "return_strings": [ + "Supervisor.on_start()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 355, + "name": "server_info", + "clauses": [ + { + "full": "@callback server_info(Plug.Conn.scheme()) :: {:ok, {inet.ip_address(), inet.port_number()} | inet.returned_non_ip_address()} | {:error, term()}", + "input_strings": [ + "Plug.Conn.scheme()" + ], + "return_strings": [ + "{:ok, {inet.ip_address(), inet.port_number()}", + "inet.returned_non_ip_address()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 0, + "line": 343, + "name": "script_name", + "clauses": [ + { + "full": "@callback script_name() :: [String.t()]", + "input_strings": [], + "return_strings": [ + "[String.t()]" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 318, + "name": "path", + "clauses": [ + { + "full": "@callback path(String.t()) :: String.t()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 4, + "line": 405, + "name": "local_broadcast_from", + "clauses": [ + { + "full": "@callback local_broadcast_from(pid(), topic(), event(), msg()) :: :ok", + "input_strings": [ + "pid()", + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 400, + "name": "local_broadcast", + "clauses": [ + { + "full": "@callback local_broadcast(topic(), event(), msg()) :: :ok", + "input_strings": [ + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 0, + "line": 348, + "name": "host", + "clauses": [ + { + "full": "@callback host() :: String.t()", + "input_strings": [], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 301, + "name": "config_change", + "clauses": [ + { + "full": "@callback config_change(term(), term()) :: term()", + "input_strings": [ + "term()", + "term()" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 296, + "name": "config", + "clauses": [ + { + "full": "@callback config(atom(), term()) :: term()", + "input_strings": [ + "atom()", + "term()" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 4, + "line": 395, + "name": "broadcast_from!", + "clauses": [ + { + "full": "@callback broadcast_from!(pid(), topic(), event(), msg()) :: :ok", + "input_strings": [ + "pid()", + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 4, + "line": 388, + "name": "broadcast_from", + "clauses": [ + { + "full": "@callback broadcast_from(pid(), topic(), event(), msg()) :: :ok | {:error, term()}", + "input_strings": [ + "pid()", + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 383, + "name": "broadcast!", + "clauses": [ + { + "full": "@callback broadcast!(topic(), event(), msg()) :: :ok", + "input_strings": [ + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 376, + "name": "broadcast", + "clauses": [ + { + "full": "@callback broadcast(topic(), event(), msg()) :: :ok | {:error, term()}", + "input_strings": [ + "topic()", + "event()", + "msg()" + ], + "return_strings": [ + ":ok", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.CodeReloader.Server": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Phoenix.Scope": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.Atom": [ + { + "arity": 1, + "line": 78, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Atom", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Atom" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 78, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.Map": [ + { + "arity": 1, + "line": 88, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Map", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Map" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 88, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Transports.LongPoll.Server": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Plug.Exception.Phoenix.ActionClauseError": [ + { + "arity": 1, + "line": 69, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Phoenix.ActionClauseError", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Phoenix.ActionClauseError" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Plug.Exception", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Plug.Exception" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 69, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.NotAcceptableError": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Release": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint.SyncCodeReloadPlug": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.Any": [ + { + "arity": 1, + "line": 95, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Any", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Any" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 95, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.Reply": [ + { + "arity": 1, + "line": 53, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.ChannelTest": [ + { + "arity": 3, + "line": 471, + "name": "push", + "clauses": [ + { + "full": "@spec push(Phoenix.Socket.t(), String.t(), map()) :: reference()", + "input_strings": [ + "Phoenix.Socket.t()", + "String.t()", + "map()" + ], + "return_strings": [ + "reference()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 486, + "name": "leave", + "clauses": [ + { + "full": "@spec leave(Phoenix.Socket.t()) :: reference()", + "input_strings": [ + "Phoenix.Socket.t()" + ], + "return_strings": [ + "reference()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Transports.LongPoll": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint.Supervisor": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Secret": [ + { + "arity": 0, + "line": 32, + "name": "invalid_args!", + "clauses": [ + { + "full": "@spec invalid_args!() :: no_return()", + "input_strings": [], + "return_strings": [ + "no_return()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.ChannelTest.NoopSerializer": [ + { + "arity": 1, + "line": 159, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Presence": [ + { + "arity": 4, + "line": 272, + "name": "update", + "clauses": [ + { + "full": "@callback update(pid(), topic(), String.t(), map() | (map() -> map())) :: {:ok, binary()} | {:error, term()}", + "input_strings": [ + "pid()", + "topic()", + "String.t()", + "map() | (map() -> map())" + ], + "return_strings": [ + "{:ok, binary()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 259, + "name": "update", + "clauses": [ + { + "full": "@callback update(Phoenix.Socket.t(), String.t(), map() | (map() -> map())) :: {:ok, binary()} | {:error, term()}", + "input_strings": [ + "Phoenix.Socket.t()", + "String.t()", + "map() | (map() -> map())" + ], + "return_strings": [ + "{:ok, binary()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 251, + "name": "untrack", + "clauses": [ + { + "full": "@callback untrack(pid(), topic(), String.t()) :: :ok", + "input_strings": [ + "pid()", + "topic()", + "String.t()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 246, + "name": "untrack", + "clauses": [ + { + "full": "@callback untrack(Phoenix.Socket.t(), String.t()) :: :ok", + "input_strings": [ + "Phoenix.Socket.t()", + "String.t()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "callback" + }, + { + "arity": 4, + "line": 239, + "name": "track", + "clauses": [ + { + "full": "@callback track(pid(), topic(), String.t(), map()) :: {:ok, binary()} | {:error, term()}", + "input_strings": [ + "pid()", + "topic()", + "String.t()", + "map()" + ], + "return_strings": [ + "{:ok, binary()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 3, + "line": 230, + "name": "track", + "clauses": [ + { + "full": "@callback track(Phoenix.Socket.t(), String.t(), map()) :: {:ok, binary()} | {:error, term()}", + "input_strings": [ + "Phoenix.Socket.t()", + "String.t()", + "map()" + ], + "return_strings": [ + "{:ok, binary()}", + "{:error, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 302, + "name": "list", + "clauses": [ + { + "full": "@callback list(Phoenix.Socket.t() | topic()) :: presences()", + "input_strings": [ + "Phoenix.Socket.t() | topic()" + ], + "return_strings": [ + "presences()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 357, + "name": "init", + "clauses": [ + { + "full": "@callback init(term()) :: {:ok, term()}", + "input_strings": [ + "term()" + ], + "return_strings": [ + "{:ok, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 4, + "line": 362, + "name": "handle_metas", + "clauses": [ + { + "full": "@callback handle_metas(String.t(), map(), map(), term()) :: {:ok, term()}", + "input_strings": [ + "String.t()", + "map()", + "map()", + "term()" + ], + "return_strings": [ + "{:ok, term()}" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 320, + "name": "get_by_key", + "clauses": [ + { + "full": "@callback get_by_key(Phoenix.Socket.t() | topic(), String.t()) :: [presence()]", + "input_strings": [ + "Phoenix.Socket.t() | topic()", + "String.t()" + ], + "return_strings": [ + "[presence()]" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 349, + "name": "fetch", + "clauses": [ + { + "full": "@callback fetch(topic(), presences()) :: presences()", + "input_strings": [ + "topic()", + "presences()" + ], + "return_strings": [ + "presences()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint.RenderErrors": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Phoenix.Schema": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Debug": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.V2.JSONSerializer": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.MissingParamError": [ + { + "arity": 1, + "line": 18, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Inspect.Phoenix.Socket.Message": [ + { + "arity": 1, + "line": 39, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: Phoenix.Socket.Message", + "input_strings": [ + ":for" + ], + "return_strings": [ + "Phoenix.Socket.Message" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Inspect", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Inspect" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 39, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.CodeReloader": [ + { + "arity": 0, + "line": 70, + "name": "sync", + "clauses": [ + { + "full": "@spec sync() :: :ok", + "input_strings": [], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 62, + "name": "reload!", + "clauses": [ + { + "full": "@spec reload!(module(), elixir.keyword()) :: :ok | {:error, binary()}", + "input_strings": [ + "module()", + "elixir.keyword()" + ], + "return_strings": [ + ":ok", + "{:error, binary()}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 54, + "name": "reload", + "clauses": [ + { + "full": "@spec reload(module(), elixir.keyword()) :: :ok | {:error, binary()}", + "input_strings": [ + "module()", + "elixir.keyword()" + ], + "return_strings": [ + ":ok", + "{:error, binary()}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 74, + "name": "child_spec", + "clauses": [ + { + "full": "@spec child_spec(elixir.keyword()) :: Supervisor.child_spec()", + "input_strings": [ + "elixir.keyword()" + ], + "return_strings": [ + "Supervisor.child_spec()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.InvalidMessageError": [ + { + "arity": 1, + "line": 250, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.V1.JSONSerializer": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.Message": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Controller.Pipeline": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Server": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Routes": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.ConnTest": [ + { + "arity": 2, + "line": 400, + "name": "text_response", + "clauses": [ + { + "full": "@spec text_response(Plug.Conn.t(), integer() | atom()) :: String.t()", + "input_strings": [ + "Plug.Conn.t()", + "integer() | atom()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 310, + "name": "response_content_type", + "clauses": [ + { + "full": "@spec response_content_type(Plug.Conn.t(), atom()) :: String.t()", + "input_strings": [ + "Plug.Conn.t()", + "atom()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 356, + "name": "response", + "clauses": [ + { + "full": "@spec response(Plug.Conn.t(), integer() | atom()) :: binary()", + "input_strings": [ + "Plug.Conn.t()", + "integer() | atom()" + ], + "return_strings": [ + "binary()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 437, + "name": "redirected_to", + "clauses": [ + { + "full": "@spec redirected_to(Plug.Conn.t(), non_neg_integer()) :: String.t()", + "input_strings": [ + "Plug.Conn.t()", + "non_neg_integer()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 589, + "name": "redirected_params", + "clauses": [ + { + "full": "@spec redirected_params(Plug.Conn.t(), non_neg_integer()) :: map()", + "input_strings": [ + "Plug.Conn.t()", + "non_neg_integer()" + ], + "return_strings": [ + "map()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 475, + "name": "recycle", + "clauses": [ + { + "full": "@spec recycle(Plug.Conn.t(), [String.t()]) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "[String.t()]" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 258, + "name": "put_req_cookie", + "clauses": [ + { + "full": "@spec put_req_cookie(Plug.Conn.t(), binary(), binary()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "binary()", + "binary()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 292, + "name": "put_flash", + "clauses": [ + { + "full": "@spec put_flash(Plug.Conn.t(), term(), term()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "term()", + "term()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 625, + "name": "path_params", + "clauses": [ + { + "full": "@spec path_params(Plug.Conn.t(), String.t()) :: map()", + "input_strings": [ + "Plug.Conn.t()", + "String.t()" + ], + "return_strings": [ + "map()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 417, + "name": "json_response", + "clauses": [ + { + "full": "@spec json_response(Plug.Conn.t(), integer() | atom()) :: term()", + "input_strings": [ + "Plug.Conn.t()", + "integer() | atom()" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 252, + "name": "init_test_session", + "clauses": [ + { + "full": "@spec init_test_session(Plug.Conn.t(), map() | elixir.keyword()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "map() | elixir.keyword()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 385, + "name": "html_response", + "clauses": [ + { + "full": "@spec html_response(Plug.Conn.t(), integer() | atom()) :: String.t()", + "input_strings": [ + "Plug.Conn.t()", + "integer() | atom()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 283, + "name": "get_flash", + "clauses": [ + { + "full": "@spec get_flash(Plug.Conn.t(), term()) :: term()", + "input_strings": [ + "Plug.Conn.t()", + "term()" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 276, + "name": "get_flash", + "clauses": [ + { + "full": "@spec get_flash(Plug.Conn.t()) :: map()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "map()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 270, + "name": "fetch_flash", + "clauses": [ + { + "full": "@spec fetch_flash(Plug.Conn.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 495, + "name": "ensure_recycled", + "clauses": [ + { + "full": "@spec ensure_recycled(Plug.Conn.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 264, + "name": "delete_req_cookie", + "clauses": [ + { + "full": "@spec delete_req_cookie(Plug.Conn.t(), binary()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "binary()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 298, + "name": "clear_flash", + "clauses": [ + { + "full": "@spec clear_flash(Plug.Conn.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 571, + "name": "bypass_through", + "clauses": [ + { + "full": "@spec bypass_through(Plug.Conn.t(), module(), atom() | list()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "module()", + "atom() | list()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 561, + "name": "bypass_through", + "clauses": [ + { + "full": "@spec bypass_through(Plug.Conn.t(), module()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()", + "module()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 551, + "name": "bypass_through", + "clauses": [ + { + "full": "@spec bypass_through(Plug.Conn.t()) :: Plug.Conn.t()", + "input_strings": [ + "Plug.Conn.t()" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 150, + "name": "build_conn", + "clauses": [ + { + "full": "@spec build_conn(atom() | binary(), binary(), binary() | list() | map() | nil) :: Plug.Conn.t()", + "input_strings": [ + "atom() | binary()", + "binary()", + "binary() | list() | map() | nil" + ], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 0, + "line": 138, + "name": "build_conn", + "clauses": [ + { + "full": "@spec build_conn() :: Plug.Conn.t()", + "input_strings": [], + "return_strings": [ + "Plug.Conn.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 676, + "name": "assert_error_sent", + "clauses": [ + { + "full": "@spec assert_error_sent(integer() | atom(), function()) :: {integer(), list(), term()}", + "input_strings": [ + "integer() | atom()", + "function()" + ], + "return_strings": [ + "{integer(), list(), term()}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Live": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.Broadcast": [ + { + "arity": 1, + "line": 71, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.MalformedURIError": [ + { + "arity": 1, + "line": 21, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Presence.Tracker": [ + { + "arity": 1, + "line": 427, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Transports.WebSocket": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.ConsoleFormatter": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Compile.Phoenix": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Socket.PoolSupervisor": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Endpoint.Cowboy2Adapter": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Config": [ + { + "arity": 1, + "line": 78, + "name": "clear_cache", + "clauses": [ + { + "full": "@spec clear_cache(module()) :: :ok", + "input_strings": [ + "module()" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "spec" + }, + { + "arity": 3, + "line": 46, + "name": "cache", + "clauses": [ + { + "full": "@spec cache(module(), term(), (module() -> {:cache | :nocache, term()})) :: term()", + "input_strings": [ + "module()", + "term()", + "(module() -> {:cache | :nocache, term()})" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Digester.Compressor": [ + { + "arity": 0, + "line": 43, + "name": "file_extensions", + "clauses": [ + { + "full": "@callback file_extensions() :: nonempty_list(String.t())", + "input_strings": [], + "return_strings": [ + "nonempty_list(String.t())" + ] + } + ], + "kind": "callback" + }, + { + "arity": 2, + "line": 42, + "name": "compress_file", + "clauses": [ + { + "full": "@callback compress_file(Path.t(), binary()) :: {:ok, binary()} | :error", + "input_strings": [ + "Path.t()", + "binary()" + ], + "return_strings": [ + "{:ok, binary()}", + ":error" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Digester": [ + { + "arity": 3, + "line": 19, + "name": "compile", + "clauses": [ + { + "full": "@spec compile(String.t(), String.t(), boolean()) :: :ok | {:error, :invalid_path}", + "input_strings": [ + "String.t()", + "String.t()", + "boolean()" + ], + "return_strings": [ + ":ok", + "{:error, :invalid_path}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 355, + "name": "clean_all", + "clauses": [ + { + "full": "@spec clean_all(String.t()) :: :ok | {:error, :invalid_path}", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + ":ok", + "{:error, :invalid_path}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 4, + "line": 334, + "name": "clean", + "clauses": [ + { + "full": "@spec clean(String.t(), integer(), integer(), integer()) :: :ok | {:error, :invalid_path}", + "input_strings": [ + "String.t()", + "integer()", + "integer()", + "integer()" + ], + "return_strings": [ + ":ok", + "{:error, :invalid_path}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.CodeReloader.MixListener": [ + { + "arity": 0, + "line": 13, + "name": "started?", + "clauses": [ + { + "full": "@spec started?() :: boolean()", + "input_strings": [], + "return_strings": [ + "boolean()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 8, + "name": "start_link", + "clauses": [ + { + "full": "@spec start_link(elixir.keyword()) :: GenServer.on_start()", + "input_strings": [ + "elixir.keyword()" + ], + "return_strings": [ + "GenServer.on_start()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 23, + "name": "purge", + "clauses": [ + { + "full": "@spec purge([atom()]) :: :ok", + "input_strings": [ + "[atom()]" + ], + "return_strings": [ + ":ok" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.VerifiedRoutes": [ + { + "arity": 2, + "line": 295, + "name": "verified_route?", + "clauses": [ + { + "full": "@callback verified_route?(plug_opts(), [String.t()]) :: boolean()", + "input_strings": [ + "plug_opts()", + "[String.t()]" + ], + "return_strings": [ + "boolean()" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 287, + "name": "formatted_routes", + "clauses": [ + { + "full": "@callback formatted_routes(plug_opts()) :: [formatted_route()]", + "input_strings": [ + "plug_opts()" + ], + "return_strings": [ + "[formatted_route()]" + ] + } + ], + "kind": "callback" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Json": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Param.BitString": [ + { + "arity": 1, + "line": 74, + "name": "__impl__", + "clauses": [ + { + "full": "@spec __impl__(:for) :: BitString", + "input_strings": [ + ":for" + ], + "return_strings": [ + "BitString" + ] + }, + { + "full": "@spec __impl__(:protocol) :: Phoenix.Param", + "input_strings": [ + ":protocol" + ], + "return_strings": [ + "Phoenix.Param" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 74, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Phoenix": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Phoenix.Context": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Context": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Token": [ + { + "arity": 4, + "line": 218, + "name": "verify", + "clauses": [ + { + "full": "@spec verify(context(), binary(), binary(), [shared_opt() | max_age_opt()]) :: {:ok, term()} | {:error, :expired | :invalid | :missing}", + "input_strings": [ + "context()", + "binary()", + "binary()", + "[shared_opt() | max_age_opt()]" + ], + "return_strings": [ + "{:ok, term()}", + "{:error, :expired", + ":invalid", + ":missing}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 4, + "line": 132, + "name": "sign", + "clauses": [ + { + "full": "@spec sign(context(), binary(), term(), [shared_opt() | max_age_opt() | signed_at_opt()]) :: binary()", + "input_strings": [ + "context()", + "binary()", + "term()", + "[shared_opt() | max_age_opt() | signed_at_opt()]" + ], + "return_strings": [ + "binary()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 4, + "line": 158, + "name": "encrypt", + "clauses": [ + { + "full": "@spec encrypt(context(), binary(), term(), [shared_opt() | max_age_opt() | signed_at_opt()]) :: binary()", + "input_strings": [ + "context()", + "binary()", + "term()", + "[shared_opt() | max_age_opt() | signed_at_opt()]" + ], + "return_strings": [ + "binary()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 4, + "line": 243, + "name": "decrypt", + "clauses": [ + { + "full": "@spec decrypt(context(), binary(), binary(), [shared_opt() | max_age_opt()]) :: term()", + "input_strings": [ + "context()", + "binary()", + "binary()", + "[shared_opt() | max_age_opt()]" + ], + "return_strings": [ + "term()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.Scope": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.Route": [ + { + "arity": 14, + "line": 63, + "name": "build", + "clauses": [ + { + "full": "@spec build(non_neg_integer(), :match | :forward, atom(), String.t(), String.t() | nil, atom(), atom(), atom() | nil, [atom()], map(), map(), map(), boolean(), boolean()) :: t()", + "input_strings": [ + "non_neg_integer()", + ":match | :forward", + "atom()", + "String.t()", + "String.t() | nil", + "atom()", + "atom()", + "atom() | nil", + "[atom()]", + "map()", + "map()", + "map()", + "boolean()", + "boolean()" + ], + "return_strings": [ + "t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Auth": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Auth.Injector": [ + { + "arity": 2, + "line": 63, + "name": "test_config_inject", + "clauses": [ + { + "full": "@spec test_config_inject(String.t(), Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", + "input_strings": [ + "String.t()", + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()" + ], + "return_strings": [ + "{:ok, String.t()}", + ":already_injected", + "{:error, :unable_to_inject}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 77, + "name": "test_config_help_text", + "clauses": [ + { + "full": "@spec test_config_help_text(String.t(), Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()) :: String.t()", + "input_strings": [ + "String.t()", + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 291, + "name": "split_with_self", + "clauses": [ + { + "full": "@spec split_with_self(String.t(), String.t()) :: {String.t(), String.t(), String.t()} | :error", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "{String.t(), String.t(), String.t()}", + ":error" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 98, + "name": "router_plug_inject", + "clauses": [ + { + "full": "@spec router_plug_inject(String.t(), elixir.keyword()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", + "input_strings": [ + "String.t()", + "elixir.keyword()" + ], + "return_strings": [ + "{:ok, String.t()}", + ":already_injected", + "{:error, :unable_to_inject}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 120, + "name": "router_plug_help_text", + "clauses": [ + { + "full": "@spec router_plug_help_text(String.t(), elixir.keyword()) :: String.t()", + "input_strings": [ + "String.t()", + "elixir.keyword()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 299, + "name": "normalize_line_endings_to_file", + "clauses": [ + { + "full": "@spec normalize_line_endings_to_file(String.t(), String.t()) :: String.t()", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 12, + "name": "mix_dependency_inject", + "clauses": [ + { + "full": "@spec mix_dependency_inject(String.t(), String.t()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "{:ok, String.t()}", + ":already_injected", + "{:error, :unable_to_inject}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 265, + "name": "inject_before_final_end", + "clauses": [ + { + "full": "@spec inject_before_final_end(String.t(), String.t()) :: {:ok, String.t()} | :already_injected", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "{:ok, String.t()}", + ":already_injected" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 304, + "name": "get_line_ending", + "clauses": [ + { + "full": "@spec get_line_ending(String.t()) :: String.t()", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "String.t()" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 282, + "name": "ensure_not_already_injected", + "clauses": [ + { + "full": "@spec ensure_not_already_injected(String.t(), String.t()) :: :ok | :already_injected", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + ":ok", + ":already_injected" + ] + } + ], + "kind": "spec" + }, + { + "arity": 2, + "line": 21, + "name": "do_mix_dependency_inject", + "clauses": [ + { + "full": "@spec do_mix_dependency_inject(String.t(), String.t()) :: {:ok, String.t()} | {:error, :unable_to_inject}", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "{:ok, String.t()}", + "{:error, :unable_to_inject}" + ] + } + ], + "kind": "spec" + }, + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Phoenix.Router.Resource": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Cert": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Auth.Migration": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Gen.Presence": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ], + "Mix.Tasks.Phx.Digest.Clean": [ + { + "arity": 1, + "line": 1, + "name": "__info__", + "clauses": [ + { + "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", + "input_strings": [ + ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" + ], + "return_strings": [ + "any()" + ] + } + ], + "kind": "spec" + } + ] + }, + "structs": { + "Mix.Phoenix.Context": { + "fields": [ + { + "default": "nil", + "field": "name", + "required": false + }, + { + "default": "nil", + "field": "module", + "required": false + }, + { + "default": "nil", + "field": "schema", + "required": false + }, + { + "default": "nil", + "field": "alias", + "required": false + }, + { + "default": "nil", + "field": "base_module", + "required": false + }, + { + "default": "nil", + "field": "web_module", + "required": false + }, + { + "default": "nil", + "field": "basename", + "required": false + }, + { + "default": "nil", + "field": "file", + "required": false + }, + { + "default": "nil", + "field": "test_file", + "required": false + }, + { + "default": "nil", + "field": "test_fixtures_file", + "required": false + }, + { + "default": "nil", + "field": "dir", + "required": false + }, + { + "default": "true", + "field": "generate?", + "required": false + }, + { + "default": "nil", + "field": "context_app", + "required": false + }, + { + "default": "[]", + "field": "opts", + "required": false + }, + { + "default": "nil", + "field": "scope", + "required": false + } + ] + }, + "Mix.Phoenix.Schema": { + "fields": [ + { + "default": "nil", + "field": "module", + "required": false + }, + { + "default": "nil", + "field": "repo", + "required": false + }, + { + "default": "nil", + "field": "repo_alias", + "required": false + }, + { + "default": "nil", + "field": "table", + "required": false + }, + { + "default": "nil", + "field": "collection", + "required": false + }, + { + "default": "false", + "field": "embedded?", + "required": false + }, + { + "default": "true", + "field": "generate?", + "required": false + }, + { + "default": "[]", + "field": "opts", + "required": false + }, + { + "default": "nil", + "field": "alias", + "required": false + }, + { + "default": "nil", + "field": "file", + "required": false + }, + { + "default": "[]", + "field": "attrs", + "required": false + }, + { + "default": "nil", + "field": "string_attr", + "required": false + }, + { + "default": "nil", + "field": "plural", + "required": false + }, + { + "default": "nil", + "field": "singular", + "required": false + }, + { + "default": "[]", + "field": "uniques", + "required": false + }, + { + "default": "[]", + "field": "redacts", + "required": false + }, + { + "default": "[]", + "field": "assocs", + "required": false + }, + { + "default": "[]", + "field": "types", + "required": false + }, + { + "default": "[]", + "field": "indexes", + "required": false + }, + { + "default": "[]", + "field": "defaults", + "required": false + }, + { + "default": "nil", + "field": "human_singular", + "required": false + }, + { + "default": "nil", + "field": "human_plural", + "required": false + }, + { + "default": "false", + "field": "binary_id", + "required": false + }, + { + "default": "nil", + "field": "migration_defaults", + "required": false + }, + { + "default": "false", + "field": "migration?", + "required": false + }, + { + "default": "%{}", + "field": "params", + "required": false + }, + { + "default": "[]", + "field": "optionals", + "required": false + }, + { + "default": "nil", + "field": "sample_id", + "required": false + }, + { + "default": "nil", + "field": "web_path", + "required": false + }, + { + "default": "nil", + "field": "web_namespace", + "required": false + }, + { + "default": "nil", + "field": "context_app", + "required": false + }, + { + "default": "nil", + "field": "route_helper", + "required": false + }, + { + "default": "nil", + "field": "route_prefix", + "required": false + }, + { + "default": "nil", + "field": "api_route_prefix", + "required": false + }, + { + "default": "nil", + "field": "migration_module", + "required": false + }, + { + "default": "[]", + "field": "fixture_unique_functions", + "required": false + }, + { + "default": "[]", + "field": "fixture_params", + "required": false + }, + { + "default": "nil", + "field": "prefix", + "required": false + }, + { + "default": ":naive_datetime", + "field": "timestamp_type", + "required": false + }, + { + "default": "nil", + "field": "scope", + "required": false + } + ] + }, + "Mix.Phoenix.Scope": { + "fields": [ + { + "default": "nil", + "field": "name", + "required": false + }, + { + "default": "false", + "field": "default", + "required": false + }, + { + "default": "nil", + "field": "module", + "required": false + }, + { + "default": "nil", + "field": "alias", + "required": false + }, + { + "default": "nil", + "field": "assign_key", + "required": false + }, + { + "default": "nil", + "field": "access_path", + "required": false + }, + { + "default": "nil", + "field": "route_prefix", + "required": false + }, + { + "default": "nil", + "field": "route_access_path", + "required": false + }, + { + "default": "nil", + "field": "schema_table", + "required": false + }, + { + "default": "nil", + "field": "schema_key", + "required": false + }, + { + "default": "nil", + "field": "schema_type", + "required": false + }, + { + "default": "nil", + "field": "schema_migration_type", + "required": false + }, + { + "default": "nil", + "field": "test_data_fixture", + "required": false + }, + { + "default": "nil", + "field": "test_setup_helper", + "required": false + } + ] + }, + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": { + "fields": [ + { + "default": "nil", + "field": "name", + "required": false + }, + { + "default": "nil", + "field": "module", + "required": false + }, + { + "default": "nil", + "field": "mix_dependency", + "required": false + }, + { + "default": "nil", + "field": "test_config", + "required": false + } + ] + }, + "Mix.Tasks.Phx.Gen.Auth.Migration": { + "fields": [ + { + "default": "nil", + "field": "ecto_adapter", + "required": false + }, + { + "default": "nil", + "field": "extensions", + "required": false + }, + { + "default": "nil", + "field": "column_definitions", + "required": false + } + ] + }, + "Phoenix.ActionClauseError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "nil", + "field": "args", + "required": false + }, + { + "default": "nil", + "field": "arity", + "required": false + }, + { + "default": "nil", + "field": "function", + "required": false + }, + { + "default": "nil", + "field": "module", + "required": false + }, + { + "default": "nil", + "field": "clauses", + "required": false + }, + { + "default": "nil", + "field": "kind", + "required": false + } + ] + }, + "Phoenix.MissingParamError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "nil", + "field": "message", + "required": false + }, + { + "default": "400", + "field": "plug_status", + "required": false + } + ] + }, + "Phoenix.NotAcceptableError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "nil", + "field": "message", + "required": false + }, + { + "default": "[]", + "field": "accepts", + "required": false + }, + { + "default": "406", + "field": "plug_status", + "required": false + } + ] + }, + "Phoenix.Router.MalformedURIError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "nil", + "field": "message", + "required": false + }, + { + "default": "400", + "field": "plug_status", + "required": false + } + ] + }, + "Phoenix.Router.NoRouteError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "404", + "field": "plug_status", + "required": false + }, + { + "default": "\"no route found\"", + "field": "message", + "required": false + }, + { + "default": "nil", + "field": "conn", + "required": false + }, + { + "default": "nil", + "field": "router", + "required": false + } + ] + }, + "Phoenix.Router.Resource": { + "fields": [ + { + "default": "nil", + "field": "path", + "required": false + }, + { + "default": "nil", + "field": "actions", + "required": false + }, + { + "default": "nil", + "field": "param", + "required": false + }, + { + "default": "nil", + "field": "route", + "required": false + }, + { + "default": "nil", + "field": "controller", + "required": false + }, + { + "default": "nil", + "field": "member", + "required": false + }, + { + "default": "nil", + "field": "collection", + "required": false + }, + { + "default": "nil", + "field": "singleton", + "required": false + } + ] + }, + "Phoenix.Router.Route": { + "fields": [ + { + "default": "nil", + "field": "verb", + "required": false + }, + { + "default": "nil", + "field": "line", + "required": false + }, + { + "default": "nil", + "field": "kind", + "required": false + }, + { + "default": "nil", + "field": "path", + "required": false + }, + { + "default": "nil", + "field": "hosts", + "required": false + }, + { + "default": "nil", + "field": "plug", + "required": false + }, + { + "default": "nil", + "field": "plug_opts", + "required": false + }, + { + "default": "nil", + "field": "helper", + "required": false + }, + { + "default": "nil", + "field": "private", + "required": false + }, + { + "default": "nil", + "field": "pipe_through", + "required": false + }, + { + "default": "nil", + "field": "assigns", + "required": false + }, + { + "default": "nil", + "field": "metadata", + "required": false + }, + { + "default": "nil", + "field": "trailing_slash?", + "required": false + }, + { + "default": "nil", + "field": "warn_on_verify?", + "required": false + } + ] + }, + "Phoenix.Router.Scope": { + "fields": [ + { + "default": "[]", + "field": "path", + "required": false + }, + { + "default": "[]", + "field": "alias", + "required": false + }, + { + "default": "[]", + "field": "as", + "required": false + }, + { + "default": "[]", + "field": "pipes", + "required": false + }, + { + "default": "[]", + "field": "hosts", + "required": false + }, + { + "default": "%{}", + "field": "private", + "required": false + }, + { + "default": "%{}", + "field": "assigns", + "required": false + }, + { + "default": ":debug", + "field": "log", + "required": false + }, + { + "default": "false", + "field": "trailing_slash?", + "required": false + } + ] + }, + "Phoenix.Socket": { + "fields": [ + { + "default": "%{}", + "field": "assigns", + "required": false + }, + { + "default": "nil", + "field": "channel", + "required": false + }, + { + "default": "nil", + "field": "channel_pid", + "required": false + }, + { + "default": "nil", + "field": "endpoint", + "required": false + }, + { + "default": "nil", + "field": "handler", + "required": false + }, + { + "default": "nil", + "field": "id", + "required": false + }, + { + "default": "false", + "field": "joined", + "required": false + }, + { + "default": "nil", + "field": "join_ref", + "required": false + }, + { + "default": "%{}", + "field": "private", + "required": false + }, + { + "default": "nil", + "field": "pubsub_server", + "required": false + }, + { + "default": "nil", + "field": "ref", + "required": false + }, + { + "default": "nil", + "field": "serializer", + "required": false + }, + { + "default": "nil", + "field": "topic", + "required": false + }, + { + "default": "nil", + "field": "transport", + "required": false + }, + { + "default": "nil", + "field": "transport_pid", + "required": false + } + ] + }, + "Phoenix.Socket.Broadcast": { + "fields": [ + { + "default": "nil", + "field": "topic", + "required": false + }, + { + "default": "nil", + "field": "event", + "required": false + }, + { + "default": "nil", + "field": "payload", + "required": false + } + ] + }, + "Phoenix.Socket.InvalidMessageError": { + "fields": [ + { + "default": "true", + "field": "__exception__", + "required": false + }, + { + "default": "nil", + "field": "message", + "required": false + } + ] + }, + "Phoenix.Socket.Message": { + "fields": [ + { + "default": "nil", + "field": "topic", + "required": false + }, + { + "default": "nil", + "field": "event", + "required": false + }, + { + "default": "nil", + "field": "payload", + "required": false + }, + { + "default": "nil", + "field": "ref", + "required": false + }, + { + "default": "nil", + "field": "join_ref", + "required": false + } + ] + }, + "Phoenix.Socket.Reply": { + "fields": [ + { + "default": "nil", + "field": "topic", + "required": false + }, + { + "default": "nil", + "field": "status", + "required": false + }, + { + "default": "nil", + "field": "payload", + "required": false + }, + { + "default": "nil", + "field": "ref", + "required": false + }, + { + "default": "nil", + "field": "join_ref", + "required": false + } + ] + }, + "Phoenix.VerifiedRoutes": { + "fields": [ + { + "default": "nil", + "field": "router", + "required": false + }, + { + "default": "nil", + "field": "route", + "required": false + }, + { + "default": "nil", + "field": "inspected_route", + "required": false + }, + { + "default": "nil", + "field": "warn_location", + "required": false + }, + { + "default": "nil", + "field": "test_path", + "required": false + } + ] + } + }, + "environment": "dev", + "project_path": "/Users/camonz/Code/phoenix", + "calls": [ + { + "caller": { + "function": "run/1", + "line": 61, + "module": "Mix.Tasks.Phx.Digest.Clean", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "output_path", + "arity": 1, + "function": "clean_all", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "run/1", + "line": 62, + "module": "Mix.Tasks.Phx.Digest.Clean", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "output_path, age, keep", + "arity": 3, + "function": "clean", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "run/1", + "line": 73, + "module": "Mix.Tasks.Phx.Digest", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "input_path, output_path, with_vsn?", + "arity": 3, + "function": "compile", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "run/1", + "line": 27, + "module": "Mix.Tasks.Phx", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "general", + "module": "Mix.Tasks.Phx" + } + }, + { + "caller": { + "function": "run/1", + "line": 20, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[\"Presence\"]", + "arity": 1, + "function": "run", + "module": "Mix.Tasks.Phx.Gen.Presence" + } + }, + { + "caller": { + "function": "run/1", + "line": 49, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Presence" + } + }, + { + "caller": { + "function": "run/1", + "line": 49, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.presence\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 42, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "context_base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 33, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "alias_name", + "arity": 1, + "function": "inflect", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 32, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 31, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 30, + "module": "Mix.Tasks.Phx.Gen.Presence", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run_args/0", + "line": 53, + "module": "Mix.Tasks.Phx.Server", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "iex_running?", + "module": "Mix.Tasks.Phx.Server" + } + }, + { + "caller": { + "function": "run/1", + "line": 36, + "module": "Mix.Tasks.Phx.Server", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "open_args", + "module": "Mix.Tasks.Phx.Server" + } + }, + { + "caller": { + "function": "run/1", + "line": 36, + "module": "Mix.Tasks.Phx.Server", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "run_args", + "module": "Mix.Tasks.Phx.Server" + } + }, + { + "caller": { + "function": "process_message/1", + "line": 46, + "module": "Inspect.Phoenix.Socket.Message", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "payload", + "arity": 1, + "function": "filter_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "inspect/2", + "line": 41, + "module": "Inspect.Phoenix.Socket.Message", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg", + "arity": 1, + "function": "process_message", + "module": "Inspect.Phoenix.Socket.Message" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 108, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Channel" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":erlang.hd(args)", + "arity": 1, + "function": "valid_name?", + "module": "Mix.Tasks.Phx.Gen.Channel" + } + }, + { + "caller": { + "function": "run/1", + "line": 80, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "String.split(<<\"User --from-channel \"::binary, String.Chars.to_string(channel_name)::binary>>)", + "arity": 1, + "function": "run", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "run/1", + "line": 64, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app, \"channels/user_socket.ex\"", + "arity": 2, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 55, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Channel" + } + }, + { + "caller": { + "function": "run/1", + "line": 54, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.channel\", binding, :erlang.++(\n [\n {:eex, \"channel.ex\",\n Path.join(\n web_prefix,\n <<\"channels/\"::binary, String.Chars.to_string(binding[:path])::binary,\n \"_channel.ex\"::binary>>\n )},\n {:eex, \"channel_test.exs\", test_path}\n ],\n maybe_case\n)", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 42, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "<>", + "arity": 1, + "function": "check_module_name_availability!", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 39, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "channel_name", + "arity": 1, + "function": "inflect", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 38, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 37, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 36, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 35, + "module": "Mix.Tasks.Phx.Gen.Channel", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Channel" + } + }, + { + "caller": { + "function": "build/1", + "line": 14, + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :bcrypt,\n module: Bcrypt,\n mix_dependency: \"{:bcrypt_elixir, \\\"~> 3.0\\\"}\",\n test_config: \"config :bcrypt_elixir, :log_rounds, 1\\n\"\n}", + "arity": 2, + "function": "%", + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" + } + }, + { + "caller": { + "function": "build/1", + "line": 27, + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :pbkdf2,\n module: Pbkdf2,\n mix_dependency: \"{:pbkdf2_elixir, \\\"~> 2.0\\\"}\",\n test_config: \"config :pbkdf2_elixir, :rounds, 1\\n\"\n}", + "arity": 2, + "function": "%", + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" + } + }, + { + "caller": { + "function": "build/1", + "line": 40, + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :argon2,\n module: Argon2,\n mix_dependency: \"{:argon2_elixir, \\\"~> 4.0\\\"}\",\n test_config: \"config :argon2_elixir, t_cost: 1, m_cost: 8\\n\"\n}", + "arity": 2, + "function": "%", + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" + } + }, + { + "caller": { + "function": "run/1", + "line": 16, + "module": "Mix.Tasks.Phx.Gen.Secret", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[\"64\"]", + "arity": 1, + "function": "run", + "module": "Mix.Tasks.Phx.Gen.Secret" + } + }, + { + "caller": { + "function": "run/1", + "line": 17, + "module": "Mix.Tasks.Phx.Gen.Secret", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "int", + "arity": 1, + "function": "parse!", + "module": "Mix.Tasks.Phx.Gen.Secret" + } + }, + { + "caller": { + "function": "run/1", + "line": 17, + "module": "Mix.Tasks.Phx.Gen.Secret", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parse!(int)", + "arity": 1, + "function": "random_string", + "module": "Mix.Tasks.Phx.Gen.Secret" + } + }, + { + "caller": { + "function": "run/1", + "line": 18, + "module": "Mix.Tasks.Phx.Gen.Secret", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "invalid_args!", + "module": "Mix.Tasks.Phx.Gen.Secret" + } + }, + { + "caller": { + "function": "parse!/1", + "line": 23, + "module": "Mix.Tasks.Phx.Gen.Secret", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "invalid_args!", + "module": "Mix.Tasks.Phx.Gen.Secret" + } + }, + { + "caller": { + "function": "touch/0", + "line": 29, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "touch_if_exists", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "touch/0", + "line": 26, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "modules", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "touch/0", + "line": 27, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.modules()", + "arity": 1, + "function": "modules_for_recompilation", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "touch/0", + "line": 28, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "modules_for_recompilation(Mix.Phoenix.modules())", + "arity": 1, + "function": "modules_to_file_paths", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 18, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "touch", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "modules_for_recompilation/1", + "line": 40, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "mod", + "arity": 1, + "function": "mix_recompile?", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "modules_for_recompilation/1", + "line": 40, + "module": "Mix.Tasks.Compile.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "mod", + "arity": 1, + "function": "phoenix_recompile?", + "module": "Mix.Tasks.Compile.Phoenix" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 93, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 92, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "pre_existing_channel", + "arity": 1, + "function": "valid_name?", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 92, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "name", + "arity": 1, + "function": "valid_name?", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 101, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 100, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "name", + "arity": 1, + "function": "valid_name?", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "run/1", + "line": 68, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app, \"endpoint.ex\"", + "arity": 2, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 61, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "run/1", + "line": 61, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.socket\", binding, [\n {:eex, \"socket.ex\",\n Path.join(\n web_prefix,\n <<\"channels/\"::binary, String.Chars.to_string(binding[:path])::binary, \"_socket.ex\"::binary>>\n )},\n {:eex, \"socket.js\",\n <<\"assets/js/\"::binary, String.Chars.to_string(binding[:path])::binary, \"_socket.js\"::binary>>}\n]", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 59, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "<>", + "arity": 1, + "function": "check_module_name_availability!", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 43, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pre_existing_channel", + "arity": 1, + "function": "inflect", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 39, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "socket_name", + "arity": 1, + "function": "inflect", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 38, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 37, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 35, + "module": "Mix.Tasks.Phx.Gen.Socket", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Socket" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 72, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "<<\"Expected the schema argument, \"::binary, Kernel.inspect(schema)::binary,\n \", to be a valid module name\"::binary>>", + "arity": 1, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 69, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema", + "arity": 1, + "function": "valid?", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 76, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "\"Invalid arguments\"", + "arity": 1, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "run/1", + "line": 50, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema, paths, [schema: schema]", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "run/1", + "line": 48, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "run/1", + "line": 46, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 44, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 95, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 96, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "files_to_be_generated(schema)", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.embedded\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 106, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "build/1", + "line": 62, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema_name, nil, attrs, opts", + "arity": 4, + "function": "new", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "build/1", + "line": 56, + "module": "Mix.Tasks.Phx.Gen.Embedded", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parsed", + "arity": 1, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Embedded" + } + }, + { + "caller": { + "function": "run/1", + "line": 170, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "run/1", + "line": 171, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, paths, binding)", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "run/1", + "line": 167, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "run/1", + "line": 165, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 160, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "\"scope\", schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 159, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn_scope, schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 140, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_code_injection", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 129, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "args, [name_optional: true]", + "arity": 2, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 177, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "context_files", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 176, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 178, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": ":erlang.++(files_to_be_generated(context), context_files(context))", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 251, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 228, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 239, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 193, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 192, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 211, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 210, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.json\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 209, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Json" + } + }, + { + "caller": { + "function": "context_files/1", + "line": 182, + "module": "Mix.Tasks.Phx.Gen.Json", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 164, + "module": "Phoenix.ChannelTest.NoopSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{join_ref: nil, ref: nil, topic: msg.topic(), event: msg.event(), payload: msg.payload()}", + "arity": 2, + "function": "%", + "module": "Phoenix.ChannelTest.NoopSerializer" + } + }, + { + "caller": { + "function": "column_definitions/1", + "line": 23, + "module": "Mix.Tasks.Phx.Gen.Auth.Migration", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "field, ecto_adapter", + "arity": 2, + "function": "column_definition", + "module": "Mix.Tasks.Phx.Gen.Auth.Migration" + } + }, + { + "caller": { + "function": "build/1", + "line": 10, + "module": "Mix.Tasks.Phx.Gen.Auth.Migration", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ecto_adapter", + "arity": 1, + "function": "column_definitions", + "module": "Mix.Tasks.Phx.Gen.Auth.Migration" + } + }, + { + "caller": { + "function": "build/1", + "line": 9, + "module": "Mix.Tasks.Phx.Gen.Auth.Migration", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ecto_adapter", + "arity": 1, + "function": "extensions", + "module": "Mix.Tasks.Phx.Gen.Auth.Migration" + } + }, + { + "caller": { + "function": "build/1", + "line": 7, + "module": "Mix.Tasks.Phx.Gen.Auth.Migration", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Auth.Migration, %{\n ecto_adapter: ecto_adapter,\n extensions: extensions(ecto_adapter),\n column_definitions: column_definitions(ecto_adapter)\n}", + "arity": 2, + "function": "%", + "module": "Mix.Tasks.Phx.Gen.Auth.Migration" + } + }, + { + "caller": { + "function": "scopes_from_config/1", + "line": 47, + "module": "Mix.Phoenix.Scope", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "name, opts", + "arity": 2, + "function": "new!", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "scope_from_opts/3", + "line": 81, + "module": "Mix.Phoenix.Scope", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app", + "arity": 1, + "function": "default_scope", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "scope_from_opts/3", + "line": 85, + "module": "Mix.Phoenix.Scope", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app", + "arity": 1, + "function": "scopes_from_config", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "default_scope/1", + "line": 54, + "module": "Mix.Phoenix.Scope", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app", + "arity": 1, + "function": "scopes_from_config", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "web_module/0", + "line": 94, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "web_module/0", + "line": 94, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "web_module/0", + "line": 92, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/3", + "line": 51, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "web_module", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "new/3", + "line": 45, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.Context, %{\n name: context_name,\n module: module,\n schema: schema,\n alias: alias,\n base_module: base,\n web_module: web_module(),\n basename: basename,\n file: file,\n test_file: test_file,\n test_fixtures_file: test_fixtures_file,\n dir: dir,\n generate?: generate?,\n context_app: ctx_app,\n opts: opts,\n scope: schema.scope()\n}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "new/3", + "line": 41, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, \"test/support/fixtures\"", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/3", + "line": 39, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, basedir", + "arity": 2, + "function": "context_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/3", + "line": 37, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, basedir", + "arity": 2, + "function": "context_lib_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/3", + "line": 35, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_name", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/3", + "line": 32, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "context_base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/3", + "line": 31, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/2", + "line": 27, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.Schema, %{\n alias: nil,\n api_route_prefix: nil,\n assocs: [],\n attrs: [],\n binary_id: false,\n collection: nil,\n context_app: nil,\n defaults: [],\n embedded?: false,\n file: nil,\n fixture_params: [],\n fixture_unique_functions: [],\n generate?: true,\n human_plural: nil,\n human_singular: nil,\n indexes: [],\n migration?: false,\n migration_defaults: nil,\n migration_module: nil,\n module: nil,\n optionals: [],\n opts: [],\n params: %{},\n plural: nil,\n prefix: nil,\n redacts: [],\n repo: nil,\n repo_alias: nil,\n route_helper: nil,\n route_prefix: nil,\n sample_id: nil,\n scope: nil,\n singular: nil,\n string_attr: nil,\n table: nil,\n timestamp_type: :naive_datetime,\n types: [],\n uniques: [],\n web_namespace: nil,\n web_path: nil\n}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "new/2", + "line": 27, + "module": "Mix.Phoenix.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context_name, %Mix.Phoenix.Schema{\n alias: nil,\n api_route_prefix: nil,\n assocs: [],\n attrs: [],\n binary_id: false,\n collection: nil,\n context_app: nil,\n defaults: [],\n embedded?: false,\n file: nil,\n fixture_params: [],\n fixture_unique_functions: [],\n generate?: true,\n human_plural: nil,\n human_singular: nil,\n indexes: [],\n migration?: false,\n migration_defaults: nil,\n migration_module: nil,\n module: nil,\n optionals: [],\n opts: [],\n params: %{},\n plural: nil,\n prefix: nil,\n redacts: [],\n repo: nil,\n repo_alias: nil,\n route_helper: nil,\n route_prefix: nil,\n sample_id: nil,\n scope: nil,\n singular: nil,\n string_attr: nil,\n table: nil,\n timestamp_type: :naive_datetime,\n types: [],\n uniques: [],\n web_namespace: nil,\n web_path: nil\n}, opts", + "arity": 3, + "function": "new", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "run/2", + "line": 87, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router_mod, endpoint_mod", + "arity": 2, + "function": "format", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "run/2", + "line": 83, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "url, {router_mod, opts}", + "arity": 2, + "function": "get_url_info", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "run/2", + "line": 78, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts[:endpoint], base", + "arity": 2, + "function": "endpoint", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "run/2", + "line": 78, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts[:router], base", + "arity": 2, + "function": "router", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "run/2", + "line": 77, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "passed_router, base", + "arity": 2, + "function": "router", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "run/1", + "line": 65, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "router/2", + "line": 142, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "old_router", + "arity": 1, + "function": "loaded", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "router/2", + "line": 142, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "web_router", + "arity": 1, + "function": "loaded", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "router/2", + "line": 140, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "base, \"Router\"", + "arity": 2, + "function": "app_mod", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "router/2", + "line": 139, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "base, \"Router\"", + "arity": 2, + "function": "web_mod", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "router/2", + "line": 158, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "arg_router", + "arity": 1, + "function": "loaded", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "get_url_info/2", + "line": 110, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, func_name", + "arity": 2, + "function": "get_line_number", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "get_url_info/2", + "line": 108, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_file_path", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "get_url_info/2", + "line": 96, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router_mod, method, path, \"\"", + "arity": 4, + "function": "route_info", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "endpoint/2", + "line": 118, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "base, \"Endpoint\"", + "arity": 2, + "function": "web_mod", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "endpoint/2", + "line": 118, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "web_mod(base, \"Endpoint\")", + "arity": 1, + "function": "loaded", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "endpoint/2", + "line": 122, + "module": "Mix.Tasks.Phx.Routes", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Module.concat([module])", + "arity": 1, + "function": "loaded", + "module": "Mix.Tasks.Phx.Routes" + } + }, + { + "caller": { + "function": "run/1", + "line": 173, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCPW\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFP\\0T\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x13\\x1DP\\x1DH\\x1DX\\x1D_\\x1DH\\x1DO\\x1DS\\x1DTx\\0\\x13\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"PHX_HOST\"\n}, <<\"[warn] Environment based URL export is missing from runtime configuration.\\n\\nAdd the following to your config/runtime.exs:\\n\\n host = System.get_env(\\\"PHX_HOST\\\") || \\\"example.com\\\"\\n\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(web_namespace)::binary,\n \".Endpoint,\\n ...,\\n url: [host: host, port: 443]\\n\"::binary>>", + "arity": 3, + "function": "post_install_instructions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 163, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCP[\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFP\\0R\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x17\\x1DP\\x1DH\\x1DX\\x1D_\\x1DS\\x1DE\\x1DR\\x1DV\\x1DE\\x1DRx\\0\\x17\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"PHX_SERVER\"\n}, <<\"[warn] Conditional server startup is missing from runtime configuration.\\n\\nAdd the following to the top of your config/runtime.exs:\\n\\n if System.get_env(\\\"PHX_SERVER\\\") do\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(web_namespace)::binary, \".Endpoint, server: true\\n end\\n\"::binary>>", + "arity": 3, + "function": "post_install_instructions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 150, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCPY\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFE\\06\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x15\\x1DE\\x1DC\\x1DT\\x1DO\\x1D_\\x1DI\\x1DP\\x1DV\\x1D6x\\0\\x15\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"ECTO_IPV6\"\n}, <<\"[warn] Conditional IPv6 support missing from runtime configuration.\\n\\nAdd the following to your config/runtime.exs:\\n\\n maybe_ipv6 = if System.get_env(\\\"ECTO_IPV6\\\") in ~w(true 1), do: [:inet6], else: []\\n\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(app_namespace)::binary,\n \".Repo,\\n ...,\\n socket_options: maybe_ipv6\\n\"::binary>>", + "arity": 3, + "function": "post_install_instructions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 139, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "app", + "arity": 1, + "function": "ecto_instructions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 131, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "docker_instructions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 115, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding, opts", + "arity": 2, + "function": "gen_docker", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 110, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "app, \"release.ex\"", + "arity": 2, + "function": "context_lib_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.release\", binding, [\n {:eex, \"rel/migrate.sh.eex\", \"rel/overlays/bin/migrate\"},\n {:eex, \"rel/migrate.bat.eex\", \"rel/overlays/bin/migrate.bat\"},\n {:eex, \"release.ex\", Mix.Phoenix.context_lib_path(app, \"release.ex\")}\n]", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 101, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "run/1", + "line": 101, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.release\", binding, [\n {:eex, \"rel/server.sh.eex\", \"rel/overlays/bin/server\"},\n {:eex, \"rel/server.bat.eex\", \"rel/overlays/bin/server.bat\"}\n]", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 93, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "app_namespace", + "arity": 1, + "function": "web_module", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 92, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 91, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 81, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "parse_args", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "parse_args/1", + "line": 193, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "socket_db_adaptor_installed?", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "parse_args/1", + "line": 192, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "ecto_sql_installed?", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "gen_docker/2", + "line": 297, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "paths", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "gen_docker/2", + "line": 297, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths(), \"priv/templates/phx.gen.release\", binding, [{:eex, \"Dockerfile.eex\", \"Dockerfile\"}, {:eex, \"dockerignore.eex\", \".dockerignore\"}]", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "gen_docker/2", + "line": 274, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "\"\", otp_vsn", + "arity": 2, + "function": "elixir_and_debian_vsn", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "gen_docker/2", + "line": 269, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "wanted_elixir_vsn, otp_vsn", + "arity": 2, + "function": "elixir_and_debian_vsn", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "gen_docker/2", + "line": 266, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_vsn", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "fetch_body!/1", + "line": 346, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "protocol_versions", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "fetch_body!/1", + "line": 323, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":ssl", + "arity": 1, + "function": "ensure_app!", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "fetch_body!/1", + "line": 322, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":inets", + "arity": 1, + "function": "ensure_app!", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "elixir_and_debian_vsn/2", + "line": 246, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url", + "arity": 1, + "function": "fetch_body!", + "module": "Mix.Tasks.Phx.Gen.Release" + } + }, + { + "caller": { + "function": "elixir_and_debian_vsn/2", + "line": 247, + "module": "Mix.Tasks.Phx.Gen.Release", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "do_call/4", + "line": 29, + "module": "Phoenix.Endpoint.SyncCodeReloadPlug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, endpoint, opts, false", + "arity": 4, + "function": "do_call", + "module": "Phoenix.Endpoint.SyncCodeReloadPlug" + } + }, + { + "caller": { + "function": "do_call/4", + "line": 28, + "module": "Phoenix.Endpoint.SyncCodeReloadPlug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "sync", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "do_call/4", + "line": 26, + "module": "Phoenix.Endpoint.SyncCodeReloadPlug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "UndefinedFunctionError, %{module: ^endpoint}", + "arity": 2, + "function": "%", + "module": "Phoenix.Endpoint.SyncCodeReloadPlug" + } + }, + { + "caller": { + "function": "call/2", + "line": 18, + "module": "Phoenix.Endpoint.SyncCodeReloadPlug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, endpoint, opts, true", + "arity": 4, + "function": "do_call", + "module": "Phoenix.Endpoint.SyncCodeReloadPlug" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 117, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture", + "arity": 1, + "function": "valid_message?", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 112, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 107, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 102, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "notifier", + "arity": 1, + "function": "valid_notifier?", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 97, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "valid?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 62, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, binding, paths", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "run/1", + "line": 63, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, binding, paths)", + "arity": 1, + "function": "maybe_print_mailer_installation_instructions", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "run/1", + "line": 55, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "run/1", + "line": 53, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 45, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "notifier_module", + "arity": 1, + "function": "inflect", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 43, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 176, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 177, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "files_to_be_generated(context)", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "parse_opts/1", + "line": 84, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Keyword.merge([context: true], opts), opts[:context_app]", + "arity": 2, + "function": "put_context_app", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 162, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.notifier\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 160, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "build/2", + "line": 73, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "notifier_module, opts", + "arity": 2, + "function": "new", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "build/2", + "line": 70, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parsed, help", + "arity": 2, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "build/2", + "line": 68, + "module": "Mix.Tasks.Phx.Gen.Notifier", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "parse_opts", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "scope_assign_route_prefix/1", + "line": 332, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "<<\"@\"::binary, String.Chars.to_string(assign_key)::binary>>, schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 171, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "run/1", + "line": 172, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, paths, binding)", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "run/1", + "line": 168, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "run/1", + "line": 166, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 161, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "scope_assign_route_prefix", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "run/1", + "line": 160, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "\"scope\", schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 159, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn_scope, schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 156, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "inputs", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "run/1", + "line": 141, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_code_injection", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 130, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "args, [name_optional: true]", + "arity": 2, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 128, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Html", + "arity": 1, + "function": "ensure_live_view_compat!", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 178, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "context_files", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 177, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 179, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": ":erlang.++(files_to_be_generated(context), context_files(context))", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 256, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 233, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 244, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "label/1", + "line": 326, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "String.Chars.to_string(key)", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 314, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 307, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 298, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "type", + "arity": 1, + "function": "default_options", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 297, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 289, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 286, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 283, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 280, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 277, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 274, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 271, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 268, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 265, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 194, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 193, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 217, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 216, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.html\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 215, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Html" + } + }, + { + "caller": { + "function": "context_files/1", + "line": 183, + "module": "Mix.Tasks.Phx.Gen.Html", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "socket_process_dict/1", + "line": 55, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "dictionary, :\"$process_label\"", + "arity": 2, + "function": "keyfind", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "socket_process_dict/1", + "line": 54, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "info, :dictionary", + "arity": 2, + "function": "keyfind", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "socket_process?/1", + "line": 78, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "pid", + "arity": 1, + "function": "socket_process_dict", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "socket/1", + "line": 161, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "channel_pid", + "arity": 1, + "function": "socket", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "socket/1", + "line": 160, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "channel_pid", + "arity": 1, + "function": "channel_process?", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "list_sockets/0", + "line": 39, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "dict, :\"$process_label\"", + "arity": 2, + "function": "keyfind", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "list_sockets/0", + "line": 38, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "pid", + "arity": 1, + "function": "socket_process_dict", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "list_channels/1", + "line": 128, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket_pid", + "arity": 1, + "function": "socket_process?", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "channel_process?/1", + "line": 90, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "dictionary, :\"$process_label\"", + "arity": 2, + "function": "keyfind", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "channel_process?/1", + "line": 89, + "module": "Phoenix.Debug", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "info, :dictionary", + "arity": 2, + "function": "keyfind", + "module": "Phoenix.Debug" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 265, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "plural", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "validate_args!/2", + "line": 263, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema", + "arity": 1, + "function": "valid?", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 291, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "ss", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 291, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "mm", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 291, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "hh", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 291, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "d", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 291, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "m", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "run/1", + "line": 177, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "run/1", + "line": 178, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(schema, paths, binding)", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "run/1", + "line": 168, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "run/1", + "line": 166, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 165, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args, []", + "arity": 2, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 183, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 184, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "files_to_be_generated(schema)", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 240, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.schema\", binding, [{:eex, \"migration.exs\", migration_path}]", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 238, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "timestamp", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 235, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, \"priv/repo/migrations/\"", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 232, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, <<\"priv/\"::binary, String.Chars.to_string(repo_name)::binary, \"/migrations/\"::binary>>", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 222, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.schema\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 221, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "build/3", + "line": 198, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema_name, plural, attrs, opts", + "arity": 4, + "function": "new", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "build/3", + "line": 195, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Keyword.merge(parent_opts, schema_opts), schema_opts[:context_app]", + "arity": 2, + "function": "put_context_app", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "build/3", + "line": 196, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "put_context_app(Keyword.merge(parent_opts, schema_opts), schema_opts[:context_app])", + "arity": 1, + "function": "maybe_update_repo_module", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "build/3", + "line": 190, + "module": "Mix.Tasks.Phx.Gen.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parsed, help", + "arity": 2, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "reply/2", + "line": 675, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket_ref, {status, %{}}", + "arity": 2, + "function": "reply", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "reply/2", + "line": 679, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "transport_pid, join_ref, ref, topic, {status, payload}, serializer", + "arity": 6, + "function": "reply", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "push/3", + "line": 630, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "transport_pid, socket.join_ref(), topic, event, message, socket.serializer()", + "arity": 6, + "function": "push", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "push/3", + "line": 629, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "assert_joined!", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "broadcast_from!/3", + "line": 602, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, channel_pid, topic, event, message", + "arity": 5, + "function": "broadcast_from!", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from!/3", + "line": 600, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "assert_joined!", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "broadcast_from/3", + "line": 592, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, channel_pid, topic, event, message", + "arity": 5, + "function": "broadcast_from", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from/3", + "line": 590, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "assert_joined!", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "broadcast!/3", + "line": 569, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, topic, event, message", + "arity": 4, + "function": "broadcast!", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast!/3", + "line": 568, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "assert_joined!", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "broadcast/3", + "line": 561, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, topic, event, message", + "arity": 4, + "function": "broadcast", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast/3", + "line": 560, + "module": "Phoenix.Channel", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "assert_joined!", + "module": "Phoenix.Channel" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 36, + "module": "Phoenix.CodeReloader.MixListener", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "modules", + "arity": 1, + "function": "purge_modules", + "module": "Phoenix.CodeReloader.MixListener" + } + }, + { + "caller": { + "function": "watch/2", + "line": 42, + "module": "Phoenix.Endpoint.Watcher", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "cd", + "module": "Phoenix.Endpoint.Watcher" + } + }, + { + "caller": { + "function": "exception/1", + "line": 37, + "module": "Phoenix.MissingParamError", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.MissingParamError, %{__exception__: true, plug_status: 400, message: msg}", + "arity": 2, + "function": "%", + "module": "Phoenix.MissingParamError" + } + }, + { + "caller": { + "function": "start_link/3", + "line": 111, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "scheme, endpoint, ref", + "arity": 3, + "function": "info", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "start_link/3", + "line": 107, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "scheme, endpoint, ref", + "arity": 3, + "function": "info", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "start_link/3", + "line": 103, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "scheme, endpoint, ref", + "arity": 3, + "function": "info", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "server_info/2", + "line": 144, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, scheme", + "arity": 2, + "function": "make_ref", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "port_to_integer/1", + "line": 137, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "System.get_env(env_var)", + "arity": 1, + "function": "port_to_integer", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "info/3", + "line": 121, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "scheme, ref", + "arity": 2, + "function": "bound_address", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "child_specs/2", + "line": 66, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "scheme, endpoint, opts, config[:code_reloader]", + "arity": 4, + "function": "child_spec", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "child_specs/2", + "line": 65, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "port", + "arity": 1, + "function": "port_to_integer", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "child_spec/4", + "line": 83, + "module": "Phoenix.Endpoint.Cowboy2Adapter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, scheme", + "arity": 2, + "function": "make_ref", + "module": "Phoenix.Endpoint.Cowboy2Adapter" + } + }, + { + "caller": { + "function": "exception/1", + "line": 15, + "module": "Phoenix.NotAcceptableError", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[message: msg]", + "arity": 1, + "function": "exception", + "module": "Phoenix.NotAcceptableError" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 45, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "from, reply, :erlang.apply(m, f, as), output", + "arity": 4, + "function": "put_chars", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 42, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "from, reply, chars, output", + "arity": 4, + "function": "put_chars", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 39, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "from, reply, :erlang.apply(m, f, as), output", + "arity": 4, + "function": "put_chars", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 36, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "from, reply, chars, output", + "arity": 4, + "function": "put_chars", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "handle_cast/2", + "line": 26, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "diagnostic_to_chars", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "diagnostic_to_chars/1", + "line": 66, + "module": "Phoenix.CodeReloader.Proxy", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "position", + "arity": 1, + "function": "position", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "validate_context!/1", + "line": 189, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "\"cannot use form as the schema name because it conflicts with the LiveView assigns!\"", + "arity": 1, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "scope_param_prefix/1", + "line": 441, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "scope_param", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "scope_assign_route_prefix/1", + "line": 449, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "<<\"@\"::binary, String.Chars.to_string(assign_key)::binary>>, schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 181, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, binding, paths", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 182, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, binding, paths)", + "arity": 1, + "function": "maybe_inject_imports", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 183, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_imports(copy_new_files(context, binding, paths))", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 178, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 176, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 171, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "scope_assign_route_prefix", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 170, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "socket_scope, schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 169, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "scope_param_prefix", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 168, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "scope_param", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 167, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "\"scope\", schema", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/1", + "line": 162, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "inputs", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 146, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_code_injection", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 135, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "validate_context!", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "run/1", + "line": 134, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "args, [name_optional: true]", + "arity": 2, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 132, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Live", + "arity": 1, + "function": "ensure_live_view_compat!", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 201, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "context_files", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 200, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 202, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": ":erlang.++(files_to_be_generated(context), context_files(context))", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 330, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "maybe_print_upgrade_info", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 329, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 311, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "live_route_instructions", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 319, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "live_route_instructions", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 317, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 300, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "maybe_inject_imports/1", + "line": 262, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, file, file_path, inject", + "arity": 4, + "function": "do_inject_imports", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "maybe_inject_imports/1", + "line": 253, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "label/1", + "line": 431, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "String.Chars.to_string(key)", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 419, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 412, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 403, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "type", + "arity": 1, + "function": "default_options", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 402, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 394, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 391, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 388, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 385, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 382, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 379, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 376, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 373, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "inputs/1", + "line": 370, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "label", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 215, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 214, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 247, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 246, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.live\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 232, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Live" + } + }, + { + "caller": { + "function": "context_files/1", + "line": 206, + "module": "Mix.Tasks.Phx.Gen.Live", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "template/1", + "line": 323, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "output", + "arity": 1, + "function": "format_output", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "sync/0", + "line": 71, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "sync", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "reload!/2", + "line": 63, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "endpoint, opts", + "arity": 2, + "function": "reload!", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "reload/2", + "line": 56, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, opts", + "arity": 2, + "function": "reload!", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "init/1", + "line": 106, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 2, + "function": "reload", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "format_output/1", + "line": 333, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "String.trim(output)", + "arity": 1, + "function": "remove_ansi_escapes", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "child_spec/1", + "line": 75, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "opts", + "arity": 1, + "function": "child_spec", + "module": "Phoenix.CodeReloader.MixListener" + } + }, + { + "caller": { + "function": "call/2", + "line": 120, + "module": "Phoenix.CodeReloader", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "output", + "arity": 1, + "function": "template", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "init/1", + "line": 444, + "module": "Phoenix.Presence.Tracker", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "state", + "arity": 1, + "function": "init", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 449, + "module": "Phoenix.Presence.Tracker", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "msg, state", + "arity": 2, + "function": "handle_info", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_diff/2", + "line": 446, + "module": "Phoenix.Presence.Tracker", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "diff, state", + "arity": 2, + "function": "handle_diff", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "update/3", + "line": 164, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "clear_cache", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "merger/3", + "line": 111, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 3, + "function": "merger", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "merge/2", + "line": 107, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 3, + "function": "merger", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "init/1", + "line": 134, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, config, []", + "arity": 3, + "function": "update", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 154, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "clear_cache", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 147, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, changed, permanent", + "arity": 3, + "function": "update", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "from_env/3", + "line": 92, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "defaults, config", + "arity": 2, + "function": "merge", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "from_env/3", + "line": 90, + "module": "Phoenix.Config", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, module", + "arity": 2, + "function": "fetch_config", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "to_param/1", + "line": 127, + "module": "Phoenix.Param.Any", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "id", + "arity": 1, + "function": "to_param", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "exception/1", + "line": 25, + "module": "Phoenix.Router.MalformedURIError", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[message: msg]", + "arity": 1, + "function": "exception", + "module": "Phoenix.Router.MalformedURIError" + } + }, + { + "caller": { + "function": "exception/1", + "line": 13, + "module": "Phoenix.Router.NoRouteError", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Router.NoRouteError, %{\n __exception__: true,\n plug_status: 404,\n message:\n <<\"no route found for \"::binary, String.Chars.to_string(conn.method())::binary, \" \"::binary,\n String.Chars.to_string(path)::binary, \" (\"::binary, Kernel.inspect(router)::binary,\n \")\"::binary>>,\n conn: conn,\n router: router\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router.NoRouteError" + } + }, + { + "caller": { + "function": "test_config_inject/2", + "line": 71, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "file, code_to_inject", + "arity": 2, + "function": "config_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "test_config_inject/2", + "line": 68, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "hashing_library", + "arity": 1, + "function": "test_config_code", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "test_config_inject/2", + "line": 69, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "test_config_code(hashing_library), file", + "arity": 2, + "function": "normalize_line_endings_to_file", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "test_config_help_text/2", + "line": 82, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "hashing_library", + "arity": 1, + "function": "test_config_code", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "test_config_help_text/2", + "line": 82, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "test_config_code(hashing_library), 4", + "arity": 2, + "function": "indent_spaces", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "router_plug_inject/2", + "line": 103, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "router_plug_code", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "router_plug_inject/2", + "line": 101, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "file, router_plug_code(binding), fn capture, capture ->\n Regex.replace(\n Regex.compile!(\n <<\"^(\\\\s*)\"::binary, \"plug :put_secure_browser_headers\"::binary,\n \".*(\\\\r\\\\n|\\\\n|$)\"::binary>>,\n \"Um\"\n ),\n capture,\n <<\"\\\\0\\\\1\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", + "arity": 3, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "router_plug_help_text/2", + "line": 128, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "router_plug_code", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "router_plug_help_text/2", + "line": 123, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "router_plug_name", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "router_plug_code/1", + "line": 134, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "router_plug_name", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "normalize_line_endings_to_file/2", + "line": 301, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file", + "arity": 1, + "function": "get_line_ending", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "mix_dependency_inject/2", + "line": 16, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mixfile, dependency", + "arity": 2, + "function": "do_mix_dependency_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "mix_dependency_inject/2", + "line": 15, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mixfile, dependency", + "arity": 2, + "function": "ensure_not_already_injected", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_unless_contains/4", + "line": 251, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "code, dup_check", + "arity": 2, + "function": "ensure_not_already_injected", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_unless_contains/3", + "line": 245, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "code, dup_check, dup_check, inject_fn", + "arity": 4, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "do_mix_dependency_inject/2", + "line": 29, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "mixfile, string_to_split_on", + "arity": 2, + "function": "split_with_self", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "config_inject/2", + "line": 45, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "file, code_to_inject, fn capture, capture ->\n Regex.replace(\n %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 2, 0, 0,\n \"ERCP\\x9D\\0\\0\\0\\0\\0\\0\\0A\\b\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\0\\0g\\0\\0\\0\\x02\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0Y\\x85\\0!\\0\\x01\\x1Du\\x1Ds\\x1De\\x1D \\x1DM\\x1Di\\x1Dx\\x1D.\\x1DC\\x1Do\\x1Dn\\x1Df\\x1Di\\x1Dgw\\0\\x1D\\x1Di\\x1Dm\\x1Dp\\x1Do\\x1Dr\\x1Dt\\x1D \\x1DC\\x1Do\\x1Dn\\x1Df\\x1Di\\x1Dgx\\0>\\x85\\0\\t\\0\\x02\\x1D\\r\\x1D\\nw\\0\\x05\\x1D\\nw\\0\\x04\\x19x\\0\\x12x\\0Y\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"(use Mix\\\\.Config|import Config)(\\\\r\\\\n|\\\\n|$)\"\n },\n capture,\n <<\"\\\\0\\\\2\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", + "arity": 3, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_at_end_of_nav_tag/2", + "line": 215, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, dup_check, code, fn capture, capture ->\n Regex.replace(\n %{\n __struct__: Regex,\n opts: [:multiline],\n re_pattern:\n {:re_pattern, 1, 0, 0,\n \"ERCP]\\0\\0\\0\\x02\\0\\0\\0A\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\0\\0>\\0\\0\\0\\x01\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x19\\x85\\0\\a\\0\\x01^\\tx\\0\\a\\x1D<\\x1D/\\x1Dn\\x1Da\\x1Dv\\x1D>x\\0\\x19\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"(\\\\s*)\"\n },\n capture,\n <>,\n global: false\n )\nend", + "arity": 4, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_at_end_of_nav_tag/2", + "line": 213, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding, padding, newline", + "arity": 3, + "function": "app_layout_menu_code_to_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_at_end_of_nav_tag/2", + "line": 212, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, \"\"", + "arity": 2, + "function": "formatting_info", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_after_opening_body_tag/2", + "line": 228, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, dup_check, code, fn capture, capture ->\n Regex.replace(\n Regex.compile!(\n <<\"^(\\\\s*)\"::binary, String.Chars.to_string(anchor_line)::binary,\n \".*(\\\\r\\\\n|\\\\n|$)\"::binary>>,\n \"Um\"\n ),\n capture,\n <<\"\\\\0\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", + "arity": 4, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_after_opening_body_tag/2", + "line": 226, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding, padding, newline", + "arity": 3, + "function": "app_layout_menu_code_to_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject_after_opening_body_tag/2", + "line": 225, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, anchor_line", + "arity": 2, + "function": "formatting_info", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject/2", + "line": 148, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding, template_str", + "arity": 2, + "function": "app_layout_menu_inject_after_opening_body_tag", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_inject/2", + "line": 146, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding, template_str", + "arity": 2, + "function": "app_layout_menu_inject_at_end_of_nav_tag", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_help_text/2", + "line": 157, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "app_layout_menu_code_to_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "app_layout_menu_code_to_inject/3", + "line": 197, + "module": "Mix.Tasks.Phx.Gen.Auth.Injector", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "template, padding, newline", + "arity": 3, + "function": "indent_spaces", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "unsuffix/2", + "line": 0, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "prefix_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "resource_name/2", + "line": 24, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "List.last(Module.split(String.Chars.to_string(alias))), suffix", + "arity": 2, + "function": "unsuffix", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "resource_name/2", + "line": 25, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "unsuffix(List.last(Module.split(String.Chars.to_string(alias))), suffix)", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "humanize/1", + "line": 121, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":erlang.atom_to_binary(atom)", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "camelize/2", + "line": 99, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "t, :lower", + "arity": 2, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "camelize/2", + "line": 103, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "h", + "arity": 1, + "function": "to_lower_char", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "camelize/2", + "line": 102, + "module": "Phoenix.Naming", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "value", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "render/6", + "line": 124, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, template, assigns", + "arity": 3, + "function": "render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/6", + "line": 119, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/6", + "line": 113, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "maybe_fetch_query_params", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "render/6", + "line": 114, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "maybe_fetch_query_params(conn), opts", + "arity": 2, + "function": "fetch_view_format", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "render/6", + "line": 116, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Plug.Conn.put_status(fetch_view_format(maybe_fetch_query_params(conn), opts), status), case opts[:root_layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\nend", + "arity": 2, + "function": "put_root_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/6", + "line": 117, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Controller.put_root_layout(\n Plug.Conn.put_status(fetch_view_format(maybe_fetch_query_params(conn), opts), status),\n case opts[:root_layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\n end\n), case opts[:layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\nend", + "arity": 2, + "function": "put_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 187, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, fallback_format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 188, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Controller.put_format(conn, fallback_format), fallback_view", + "arity": 2, + "function": "put_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 174, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, fallback_format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 175, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Controller.put_format(conn, fallback_format), fallback_view", + "arity": 2, + "function": "put_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 170, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, view", + "arity": 2, + "function": "put_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 166, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_formats/2", + "line": 163, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, Enum.map(formats, fn capture -> :erlang.element(1, capture) end)", + "arity": 2, + "function": "accepts", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "maybe_fetch_query_params/1", + "line": 132, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.Unfetched, %{}", + "arity": 2, + "function": "%", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "instrument_render_and_send/5", + "line": 85, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, status, kind, reason, stack, opts", + "arity": 6, + "function": "render", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "instrument_render_and_send/5", + "line": 72, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, kind, reason", + "arity": 3, + "function": "error_conn", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "instrument_render_and_send/5", + "line": 71, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "kind, reason", + "arity": 2, + "function": "status", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "fetch_view_format/2", + "line": 148, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, Enum.map(accepts, fn capture -> {capture, view} end)", + "arity": 2, + "function": "put_formats", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "fetch_view_format/2", + "line": 145, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, Enum.map(formats, fn {k, v} -> {:erlang.atom_to_binary(k), v} end)", + "arity": 2, + "function": "put_formats", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "__debugger_banner__/5", + "line": 104, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router", + "arity": 1, + "function": "format", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "__catch__/5", + "line": 65, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "kind, reason, stack", + "arity": 3, + "function": "maybe_raise", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "__catch__/5", + "line": 62, + "module": "Phoenix.Endpoint.RenderErrors", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, kind, reason, stack, opts", + "arity": 5, + "function": "instrument_render_and_send", + "module": "Phoenix.Endpoint.RenderErrors" + } + }, + { + "caller": { + "function": "validate_args!/3", + "line": 408, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "validate_args!/3", + "line": 403, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "validate_args!/3", + "line": 397, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "schema", + "arity": 1, + "function": "valid?", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "validate_args!/3", + "line": 392, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "valid?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "validate_args!/3", + "line": 371, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "schema_name_or_plural", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "run/1", + "line": 134, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 135, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, paths, binding)", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 131, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_code_injection", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 130, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/1", + "line": 128, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 119, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 140, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 141, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "files_to_be_generated(context)", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "prompt_for_code_injection/1", + "line": 448, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "merge_with_existing_context?", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "prompt_for_code_injection/1", + "line": 448, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "pre_existing?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "print_shell_instructions/1", + "line": 332, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "parse_opts/1", + "line": 166, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Keyword.merge([schema: true, context: true], opts), opts[:context_app]", + "arity": 2, + "function": "put_context_app", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "merge_with_existing_context?/1", + "line": 462, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_count, \"files\"", + "arity": 2, + "function": "singularize", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "merge_with_existing_context?/1", + "line": 461, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "function_count, \"functions\"", + "arity": 2, + "function": "singularize", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "merge_with_existing_context?/1", + "line": 456, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "file_count", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "merge_with_existing_context?/1", + "line": 455, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "function_count", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "maybe_print_unimplemented_fixture_functions/1", + "line": 292, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, 2", + "arity": 2, + "function": "indent", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 242, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, <<\"priv/templates/phx.gen.context/\"::binary, String.Chars.to_string(file)::binary>>, binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 243, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(\n paths,\n <<\"priv/templates/phx.gen.context/\"::binary, String.Chars.to_string(file)::binary>>,\n binding\n), test_file, binding", + "arity": 3, + "function": "inject_eex_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 232, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_test_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_test_fixture/3", + "line": 272, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "maybe_print_unimplemented_fixture_functions", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_test_fixture/3", + "line": 268, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_test_fixture/3", + "line": 269, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding)", + "arity": 1, + "function": "prepend_newline", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_test_fixture/3", + "line": 270, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding)\n), test_fixtures_file, binding", + "arity": 3, + "function": "inject_eex_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_test_fixture/3", + "line": 265, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_test_fixtures_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_schema_access/3", + "line": 211, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "schema_access_template", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_schema_access/3", + "line": 210, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, <<\"priv/templates/phx.gen.context/\"::binary,\n String.Chars.to_string(schema_access_template(context))::binary>>, binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_schema_access/3", + "line": 214, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(\n paths,\n <<\"priv/templates/phx.gen.context/\"::binary,\n String.Chars.to_string(schema_access_template(context))::binary>>,\n binding\n), file, binding", + "arity": 3, + "function": "inject_eex_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_schema_access/3", + "line": 207, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_context_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_eex_before_final_end/3", + "line": 325, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "<>, file_path", + "arity": 2, + "function": "write_file", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 180, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "ensure_test_fixtures_file_exists/3", + "line": 255, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.context/fixtures_module.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "ensure_test_fixtures_file_exists/3", + "line": 252, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "pre_existing_test_fixtures?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "ensure_test_file_exists/3", + "line": 226, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.context/context_test.exs\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "ensure_test_file_exists/3", + "line": 223, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "pre_existing_tests?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "ensure_context_file_exists/3", + "line": 201, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.context/context.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "ensure_context_file_exists/3", + "line": 198, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "pre_existing?", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 191, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_test_fixture", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 190, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_tests", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 189, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_schema_access", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 188, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema, paths, binding", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "build/2", + "line": 156, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context_name, schema, opts", + "arity": 3, + "function": "new", + "module": "Mix.Phoenix.Context" + } + }, + { + "caller": { + "function": "build/2", + "line": 155, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "[schema_module, plural | schema_args], opts, help", + "arity": 3, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Schema" + } + }, + { + "caller": { + "function": "build/2", + "line": 152, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parsed, optional, help", + "arity": 3, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "build/2", + "line": 149, + "module": "Mix.Tasks.Phx.Gen.Context", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "parse_opts", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "plug/4", + "line": 196, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "guards", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/4", + "line": 190, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, caller", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/4", + "line": 183, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "plug, caller", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/4", + "line": 179, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "plug_init_mode", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "plug/2", + "line": 174, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, opts, guards, __CALLER__", + "arity": 4, + "function": "plug", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/2", + "line": 176, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, opts, true, __CALLER__", + "arity": 4, + "function": "plug", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/1", + "line": 164, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, [], guards, __CALLER__", + "arity": 4, + "function": "plug", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "plug/1", + "line": 166, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, [], true, __CALLER__", + "arity": 4, + "function": "plug", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "escape_guards/1", + "line": 210, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "right", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "escape_guards/1", + "line": 210, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "left", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "escape_guards/1", + "line": 213, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "right", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "escape_guards/1", + "line": 213, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "left", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "escape_guards/1", + "line": 216, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "escape_guards", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "__catch__/5", + "line": 152, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "args", + "arity": 1, + "function": "exception", + "module": "Phoenix.ActionClauseError" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 88, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "Module.get_attribute(env.module(), :phoenix_fallback)", + "arity": 1, + "function": "build_fallback", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 82, + "module": "Phoenix.Controller.Pipeline", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "kind": "defmacro" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "plug_init_mode", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "validate_actions/3", + "line": 69, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "singleton", + "arity": 1, + "function": "default_actions", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "extract_actions/2", + "line": 64, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "singleton", + "arity": 1, + "function": "default_actions", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "extract_actions/2", + "line": 61, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":except, singleton, except", + "arity": 3, + "function": "validate_actions", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "extract_actions/2", + "line": 57, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":only, singleton, only", + "arity": 3, + "function": "validate_actions", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "build/3", + "line": 47, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Router.Resource, %{\n path: path,\n actions: actions,\n param: param,\n route: route,\n member: member,\n collection: collection,\n controller: controller,\n singleton: singleton\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "build/3", + "line": 40, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "options, singleton", + "arity": 2, + "function": "extract_actions", + "module": "Phoenix.Router.Resource" + } + }, + { + "caller": { + "function": "build/3", + "line": 34, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "controller, \"Controller\"", + "arity": 2, + "function": "resource_name", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "build/3", + "line": 31, + "module": "Phoenix.Router.Resource", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "path", + "arity": 1, + "function": "validate_path", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "from_map!/1", + "line": 35, + "module": "Phoenix.Socket.Message", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "<<\"missing key \"::binary, Kernel.inspect(err.key())::binary>>", + "arity": 1, + "function": "exception", + "module": "Phoenix.Socket.InvalidMessageError" + } + }, + { + "caller": { + "function": "from_map!/1", + "line": 26, + "module": "Phoenix.Socket.Message", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{\n topic: :maps.get(\"topic\", map),\n event: :maps.get(\"event\", map),\n payload: :maps.get(\"payload\", map),\n ref: :maps.get(\"ref\", map),\n join_ref: Map.get(map, \"join_ref\")\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.Message" + } + }, + { + "caller": { + "function": "web_test_path/2", + "line": 269, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "web_path/2", + "line": 211, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "modules/0", + "line": 180, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "beam_to_module", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inflect/1", + "line": 112, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "singular", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "inflect/1", + "line": 108, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "scoped", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "inflect/1", + "line": 107, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "singular", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "inflect/1", + "line": 106, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "base", + "arity": 1, + "function": "web_module", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inflect/1", + "line": 105, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "eval_from/3", + "line": 12, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "capture, source_file_path", + "arity": 2, + "function": "to_app_source", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_from/4", + "line": 35, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 2, + "function": "maybe_eex_gettext", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_from/4", + "line": 34, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 2, + "function": "maybe_heex_attr_gettext", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_from/4", + "line": 30, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "capture, source_dir", + "arity": 2, + "function": "to_app_source", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_test_path/2", + "line": 250, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ctx_app, Path.join([\"test\", String.Chars.to_string(ctx_app), rel_path])", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_lib_path/2", + "line": 243, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ctx_app, Path.join([\"lib\", String.Chars.to_string(ctx_app), rel_path])", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_base/1", + "line": 156, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "app_base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_app_path/2", + "line": 232, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ctx_app, this_app", + "arity": 2, + "function": "mix_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_app_path/2", + "line": 224, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_app/0", + "line": 259, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "this_app", + "arity": 1, + "function": "fetch_context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "context_app/0", + "line": 257, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "base/0", + "line": 145, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "base/0", + "line": 145, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app()", + "arity": 1, + "function": "app_base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "app_base/1", + "line": 161, + "module": "Mix.Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "String.Chars.to_string(app)", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "exception/1", + "line": 254, + "module": "Phoenix.Socket.InvalidMessageError", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[message: msg]", + "arity": 1, + "function": "exception", + "module": "Phoenix.Socket.InvalidMessageError" + } + }, + { + "caller": { + "function": "init/1", + "line": 50, + "module": "Phoenix.Socket.PoolSupervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "endpoint, {:socket, name}, ref", + "arity": 3, + "function": "permanent", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 760, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path, config", + "arity": 2, + "function": "socket_path", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 758, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "longpoll, Phoenix.Transports.LongPoll", + "arity": 2, + "function": "load_config", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 757, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "longpoll, opts[:auth_token]", + "arity": 2, + "function": "put_auth_token", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 749, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path, config", + "arity": 2, + "function": "socket_path", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 747, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "websocket, Phoenix.Transports.WebSocket", + "arity": 2, + "function": "load_config", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 746, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "websocket, opts[:auth_token]", + "arity": 2, + "function": "put_auth_token", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 735, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Keyword.get(opts, :longpoll, false), :erlang.++(common_config, [:window_ms, :pubsub_timeout_ms, :crypto])", + "arity": 2, + "function": "maybe_validate_keys", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "socket_paths/4", + "line": 720, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Keyword.get(opts, :websocket, true), :erlang.++(common_config, [\n :timeout,\n :max_frame_size,\n :fullsweep_after,\n :compress,\n :subprotocols,\n :error_handler\n])", + "arity": 2, + "function": "maybe_validate_keys", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "server?/2", + "line": 1092, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "otp_app, endpoint", + "arity": 2, + "function": "server?", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 415, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "server", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 414, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "plug", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 413, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "pubsub", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 412, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "config", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 649, + "module": "Phoenix.Endpoint", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "module, path, socket, socket_opts", + "arity": 4, + "function": "socket_paths", + "module": "Phoenix.Endpoint" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 10, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "map", + "arity": 1, + "function": "encode_v1_fields_only", + "module": "Phoenix.Socket.V1.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 9, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{join_ref: nil, ref: nil, topic: msg.topic(), event: msg.event(), payload: msg.payload()}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.V1.JSONSerializer" + } + }, + { + "caller": { + "function": "encode_v1_fields_only/1", + "line": 45, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 22, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "map", + "arity": 1, + "function": "encode_v1_fields_only", + "module": "Phoenix.Socket.V1.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 15, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{\n join_ref: nil,\n topic: reply.topic(),\n event: \"phx_reply\",\n ref: reply.ref(),\n payload: %{status: reply.status(), response: reply.payload()}\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.V1.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 26, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "map", + "arity": 1, + "function": "encode_v1_fields_only", + "module": "Phoenix.Socket.V1.JSONSerializer" + } + }, + { + "caller": { + "function": "decode!/2", + "line": 35, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "payload", + "arity": 1, + "function": "from_map!", + "module": "Phoenix.Socket.Message" + } + }, + { + "caller": { + "function": "decode!/2", + "line": 31, + "module": "Phoenix.Socket.V1.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "format_route/3", + "line": 112, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "router, Map.get(route, :helper)", + "arity": 2, + "function": "route_name", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format_route/3", + "line": 111, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "verb", + "arity": 1, + "function": "verb_name", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format_endpoint/2", + "line": 32, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, widths", + "arity": 2, + "function": "format_longpoll", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format_endpoint/2", + "line": 32, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, widths", + "arity": 2, + "function": "format_websocket", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format/2", + "line": 19, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, column_widths", + "arity": 2, + "function": "format_endpoint", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format/2", + "line": 18, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "capture, router, column_widths", + "arity": 3, + "function": "format_route", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "format/2", + "line": 15, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "router, routes, endpoint", + "arity": 3, + "function": "calculate_column_widths", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "calculate_column_widths/3", + "line": 95, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "socket_verbs", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "calculate_column_widths/3", + "line": 85, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "router, helper", + "arity": 2, + "function": "route_name", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "calculate_column_widths/3", + "line": 83, + "module": "Phoenix.Router.ConsoleFormatter", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "verb", + "arity": 1, + "function": "verb_name", + "module": "Phoenix.Router.ConsoleFormatter" + } + }, + { + "caller": { + "function": "terminate/2", + "line": 129, + "module": "Phoenix.Socket.PoolDrainer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{payload: nil, topic: nil, event: \"phx_drain\"}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.PoolDrainer" + } + }, + { + "caller": { + "function": "start/2", + "line": 26, + "module": "Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "install", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "start/2", + "line": 22, + "module": "Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "filter", + "arity": 1, + "function": "compile_filter", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "start/2", + "line": 14, + "module": "Phoenix", + "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "warn_on_missing_json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "run/1", + "line": 85, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "keyfile, certfile", + "arity": 2, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "run/1", + "line": 70, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "2048, name, hostnames", + "arity": 3, + "function": "certificate_and_key", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "print_shell_instructions/2", + "line": 124, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "base", + "arity": 1, + "function": "web_module", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/2", + "line": 117, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "print_shell_instructions/2", + "line": 116, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new_cert/3", + "line": 264, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "public_key, hostnames", + "arity": 2, + "function": "extensions", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "new_cert/3", + "line": 258, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "common_name", + "arity": 1, + "function": "rdn", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "new_cert/3", + "line": 252, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "common_name", + "arity": 1, + "function": "rdn", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "new_cert/3", + "line": 0, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "64", + "arity": 1, + "function": "size", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "extensions/2", + "line": 296, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "public_key", + "arity": 1, + "function": "key_identifier", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "certificate_and_key/3", + "line": 109, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "public_key, name, hostnames", + "arity": 3, + "function": "new_cert", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "certificate_and_key/3", + "line": 105, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "private_key", + "arity": 1, + "function": "extract_public_key", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "certificate_and_key/3", + "line": 91, + "module": "Mix.Tasks.Phx.Gen.Cert", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key_size, 65537", + "arity": 2, + "function": "generate_rsa_key", + "module": "Mix.Tasks.Phx.Gen.Cert" + } + }, + { + "caller": { + "function": "to_param/1", + "line": 63, + "module": "Phoenix.Param", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "term", + "arity": 1, + "function": "impl_for!", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "impl_for!/1", + "line": 1, + "module": "Phoenix.Param", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "data", + "arity": 1, + "function": "impl_for", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "impl_for/1", + "line": 1, + "module": "Phoenix.Param", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "struct", + "arity": 1, + "function": "struct_impl_for", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "maybe_auth_token_from_header/2", + "line": 116, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_private(conn, :phoenix_transport_auth_token, token), actual_subprotocols", + "arity": 2, + "function": "set_actual_subprotocols", + "module": "Phoenix.Transports.WebSocket" + } + }, + { + "caller": { + "function": "call/2", + "line": 65, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn, endpoint, keys, Keyword.take(opts, [:check_csrf])", + "arity": 4, + "function": "connect_info", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 52, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Plug.Conn.fetch_query_params(conn), endpoint, opts", + "arity": 3, + "function": "code_reload", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 53, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts), opts[:transport_log]", + "arity": 2, + "function": "transport_log", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 54, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n), handler, endpoint, opts", + "arity": 4, + "function": "check_origin", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 55, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts\n), opts[:auth_token]", + "arity": 2, + "function": "maybe_auth_token_from_header", + "module": "Phoenix.Transports.WebSocket" + } + }, + { + "caller": { + "function": "call/2", + "line": 56, + "module": "Phoenix.Transports.WebSocket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "maybe_auth_token_from_header(\n Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts\n ),\n opts[:auth_token]\n), subprotocols", + "arity": 2, + "function": "check_subprotocols", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "event_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "topic_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 14, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg.event(), :event, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 13, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg.topic(), :topic, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "fastlane!/1", + "line": 29, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "status_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "topic_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ref_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "join_ref_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 45, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "status, :status, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 44, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "reply.topic(), :topic, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 43, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ref, :ref, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 42, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "join_ref, :join_ref, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 72, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "event_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "topic_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "join_ref_size", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 0, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "8", + "arity": 1, + "function": "size", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 79, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg.event(), :event, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 78, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg.topic(), :topic, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 77, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "join_ref, :join_ref, 255", + "arity": 3, + "function": "byte_size!", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "encode!/1", + "line": 97, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "decode_text/1", + "line": 115, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{topic: topic, event: event, payload: payload, ref: ref, join_ref: join_ref}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "decode_text/1", + "line": 113, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "decode_binary/1", + "line": 136, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{topic: topic, event: event, payload: {:binary, data}, ref: ref, join_ref: join_ref}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "decode!/2", + "line": 108, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "raw_message", + "arity": 1, + "function": "decode_binary", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "decode!/2", + "line": 107, + "module": "Phoenix.Socket.V2.JSONSerializer", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "raw_message", + "arity": 1, + "function": "decode_text", + "module": "Phoenix.Socket.V2.JSONSerializer" + } + }, + { + "caller": { + "function": "verify/4", + "line": 222, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "get_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "sign/4", + "line": 135, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "get_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "get_key_base/1", + "line": 253, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "endpoint_module", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "get_key_base/1", + "line": 253, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Controller.endpoint_module(conn)", + "arity": 1, + "function": "get_endpoint_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "get_key_base/1", + "line": 256, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "get_endpoint_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "get_key_base/1", + "line": 259, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "get_endpoint_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "encrypt/4", + "line": 161, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "get_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "decrypt/4", + "line": 246, + "module": "Phoenix.Token", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "get_key_base", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "next_task/1", + "line": 588, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "next, ref", + "arity": 2, + "function": "send_continue", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "next_task/1", + "line": 587, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Task, %{}", + "arity": 2, + "function": "%", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "merge_diff/3", + "line": 661, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "updated_topics, topic", + "arity": 2, + "function": "remove_topic", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "merge_diff/3", + "line": 660, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "updated_topics, topic", + "arity": 2, + "function": "topic_presences_count", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "merge_diff/3", + "line": 657, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 2, + "function": "handle_leave", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "merge_diff/3", + "line": 656, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 2, + "function": "handle_join", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "merge_diff/3", + "line": 652, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "topics, topic", + "arity": 2, + "function": "add_new_topic", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "list/2", + "line": 552, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Tracker.list(module, topic)", + "arity": 1, + "function": "group", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_leave/2", + "line": 673, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "topics, topic, left_key, presence", + "arity": 4, + "function": "remove_presence_or_metas", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_join/2", + "line": 669, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "topics, topic, joined_key, joined_metas", + "arity": 4, + "function": "add_new_presence_or_metas", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 544, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "new_state", + "arity": 1, + "function": "next_task", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 539, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, computed_diffs", + "arity": 2, + "function": "do_handle_metas", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 528, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: \"presence_diff\", payload: presence_diff}", + "arity": 2, + "function": "%", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 524, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Task, %{ref: ^task_ref}", + "arity": 2, + "function": "%", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "handle_diff/2", + "line": 518, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, diff", + "arity": 2, + "function": "async_merge", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "do_handle_metas/2", + "line": 598, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "acc.topics(), topic, presence_diff", + "arity": 3, + "function": "merge_diff", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "async_merge/2", + "line": 641, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "new_task, ref", + "arity": 2, + "function": "send_continue", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "async_merge/2", + "line": 629, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "leaves", + "arity": 1, + "function": "group", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "async_merge/2", + "line": 628, + "module": "Phoenix.Presence", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "joins", + "arity": 1, + "function": "group", + "module": "Phoenix.Presence" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 131, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route.verb()", + "arity": 1, + "function": "verb_match", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 130, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route", + "arity": 1, + "function": "build_prepare", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 129, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "build_path_params", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 128, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route.hosts()", + "arity": 1, + "function": "build_host_match", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 127, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route", + "arity": 1, + "function": "build_dispatch", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "exprs/1", + "line": 122, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route", + "arity": 1, + "function": "build_path_and_binding", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "build_prepare/1", + "line": 175, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":assigns, route.assigns()", + "arity": 2, + "function": "build_prepare_expr", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "build_prepare/1", + "line": 174, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":private, route.private()", + "arity": 2, + "function": "build_prepare_expr", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "build_prepare/1", + "line": 173, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_params", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "build_path_and_binding/1", + "line": 153, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "segments", + "arity": 1, + "function": "rewrite_segments", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "build/14", + "line": 100, + "module": "Phoenix.Router.Route", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Router.Route, %{\n kind: kind,\n verb: verb,\n path: path,\n hosts: hosts,\n private: private,\n plug: plug,\n plug_opts: plug_opts,\n helper: helper,\n pipe_through: pipe_through,\n assigns: assigns,\n line: line,\n metadata: metadata,\n trailing_slash?: trailing_slash?,\n warn_on_verify?: warn_on_verify?\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "run_compilers/4", + "line": 406, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, args, status, diagnostics", + "arity": 4, + "function": "run_compilers", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "run_compilers/4", + "line": 405, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, args, :ok, diagnostics", + "arity": 4, + "function": "run_compilers", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "run_compilers/4", + "line": 400, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "compiler, args", + "arity": 2, + "function": "run_compiler", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "run_compiler/2", + "line": 411, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Task.run(<<\"compile.\"::binary, String.Chars.to_string(compiler)::binary>>, args), compiler", + "arity": 2, + "function": "normalize", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "purge_modules/1", + "line": 366, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":erlang.binary_to_atom(module)", + "arity": 1, + "function": "purge_module", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "proxy_io/1", + "line": 386, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "proxy_gl", + "arity": 1, + "function": "stop", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "proxy_io/1", + "line": 382, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "start", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "mix_compile_unless_stale_config/5", + "line": 305, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "compilers, compile_args, config, path", + "arity": 4, + "function": "mix_compile", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile_unless_stale_config/5", + "line": 302, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Path.join(Mix.Project.app_path(config), \"ebin\")", + "arity": 1, + "function": "purge_modules", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile_project/7", + "line": 287, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "compilers, compile_args, timestamp, path, purge_fallback?", + "arity": 5, + "function": "mix_compile_unless_stale_config", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile_deps/7", + "line": 270, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "compilers, compile_args, timestamp, path, purge_fallback?", + "arity": 5, + "function": "mix_compile_unless_stale_config", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile/6", + "line": 246, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "purge_modules", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile/6", + "line": 231, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "config[:app], apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", + "arity": 7, + "function": "mix_compile_project", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile/6", + "line": 221, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Dep.cached(), apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", + "arity": 7, + "function": "mix_compile_deps", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile/4", + "line": 341, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": ":erlang.group_leader(), diagnostics", + "arity": 2, + "function": "diagnostics", + "module": "Phoenix.CodeReloader.Proxy" + } + }, + { + "caller": { + "function": "mix_compile/4", + "line": 338, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "compilers, args, :noop, []", + "arity": 4, + "function": "run_compilers", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "mix_compile/4", + "line": 337, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "config, fn -> run_compilers(compilers, args, :noop, []) end", + "arity": 2, + "function": "with_logger_app", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "load_backup/1", + "line": 163, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":code.which(mod)", + "arity": 1, + "function": "read_backup", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "init/1", + "line": 34, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "timestamp", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 53, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":os.type()", + "arity": 1, + "function": "os_symlink", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 47, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "can_symlink?", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 113, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "timestamp", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 108, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "backup", + "arity": 1, + "function": "write_backup", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 88, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?", + "arity": 6, + "function": "mix_compile", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 85, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "fn ->\n try do\n task_loaded = Code.ensure_loaded(Mix.Task)\n mix_compile(task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?)\n catch\n :exit, {:shutdown, 1} ->\n :error\n\n kind, reason ->\n IO.puts(Exception.format(kind, reason, __STACKTRACE__))\n :error\n end\nend", + "arity": 1, + "function": "proxy_io", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 82, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "load_backup", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 73, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "apps", + "arity": 1, + "function": "purge", + "module": "Phoenix.CodeReloader.MixListener" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 76, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "warn_missing_mix_listener", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 72, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "started?", + "module": "Phoenix.CodeReloader.MixListener" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 70, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "fn ->\n purge_fallback? =\n case Phoenix.CodeReloader.MixListener.started?() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n warn_missing_mix_listener()\n true\n\n _ ->\n Phoenix.CodeReloader.MixListener.purge(apps)\n false\n end\n\n backup = load_backup(endpoint)\n\n {res, out} =\n proxy_io(fn ->\n try do\n task_loaded = Code.ensure_loaded(Mix.Task)\n mix_compile(task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?)\n catch\n :exit, {:shutdown, 1} ->\n :error\n\n kind, reason ->\n IO.puts(Exception.format(kind, reason, __STACKTRACE__))\n :error\n end\n end)\n\n {backup, res, out}\nend", + "arity": 1, + "function": "with_build_lock", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 67, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "[from], endpoint", + "arity": 2, + "function": "all_waiting", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 64, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "default_reloadable_apps", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "all_waiting/2", + "line": 180, + "module": "Phoenix.CodeReloader.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "[from | acc], endpoint", + "arity": 2, + "function": "all_waiting", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "reply/6", + "line": 262, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{topic: topic, join_ref: join_ref, ref: ref, status: status, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "push/6", + "line": 250, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{ref: nil, join_ref: join_ref, topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "local_broadcast_from/5", + "line": 233, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "local_broadcast/4", + "line": 216, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "join/4", + "line": 20, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 3, + "function": "start_child", + "module": "Phoenix.Socket.PoolSupervisor" + } + }, + { + "caller": { + "function": "handle_result/2", + "line": 455, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reason", + "arity": 2, + "function": "send_socket_close", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_result/2", + "line": 454, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reason", + "arity": 2, + "function": "send_socket_close", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_result/2", + "line": 453, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reason", + "arity": 2, + "function": "send_socket_close", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_reply/2", + "line": 528, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket.transport_pid(), socket.join_ref(), socket.ref(), socket.topic(), {status, payload}, socket.serializer()", + "arity": 6, + "function": "reply", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_reply/2", + "line": 539, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, {status, %{}}", + "arity": 2, + "function": "handle_reply", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 315, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "channel, topic, auth_payload, socket", + "arity": 4, + "function": "channel_join", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 324, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "{:stop, {:shutdown, :left}, :ok, Map.update!(socket, :ref, fn _ -> ref end)}", + "arity": 1, + "function": "handle_in", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 336, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "result", + "arity": 1, + "function": "handle_in", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 353, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket.channel.handle_out(event, payload, socket), :handle_out", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 369, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket.channel.handle_info(msg, socket), :handle_info", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 371, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":handle_info, 2, msg, channel", + "arity": 4, + "function": "warn_unexpected_msg", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_in/1", + "line": 514, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "handle_reply", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_in/1", + "line": 520, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "{:stop, reason, socket}, :handle_in", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_in/1", + "line": 519, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "handle_reply", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_in/1", + "line": 524, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "other, :handle_in", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_cast/2", + "line": 295, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket.channel.handle_cast(msg, socket), :handle_cast", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_call/3", + "line": 283, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket.channel.handle_call(msg, from, socket), :handle_call", + "arity": 2, + "function": "handle_result", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "channel_join/4", + "line": 406, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, channel, topic", + "arity": 3, + "function": "init_join", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "channel_join/4", + "line": 403, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, channel, topic", + "arity": 3, + "function": "init_join", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from!/5", + "line": 199, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from/5", + "line": 182, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast!/4", + "line": 165, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast/4", + "line": 148, + "module": "Phoenix.Channel.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", + "arity": 2, + "function": "%", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "publish_reply/2", + "line": 141, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "publish_reply/2", + "line": 141, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state, Phoenix.json_library().encode_to_iodata!(reply)", + "arity": 2, + "function": "publish_reply", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "publish_reply/2", + "line": 145, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state", + "arity": 1, + "function": "notify_client_now_available", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "notify_client_now_available/1", + "line": 151, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {:now_available, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "init/1", + "line": 37, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state.window_ms()", + "arity": 1, + "function": "schedule_inactive_shutdown", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "init/1", + "line": 32, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now_ms", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 65, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {:error, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 60, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {:ok, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 56, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, reply", + "arity": 2, + "function": "publish_reply", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 55, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {status, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 71, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {:subscribe, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 82, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now_ms", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 81, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, client_ref, {:messages, Enum.reverse(buffer), ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 78, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now_ms", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 100, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state.window_ms()", + "arity": 1, + "function": "schedule_inactive_shutdown", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 97, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now_ms", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "handle_info/2", + "line": 111, + "module": "Phoenix.Transports.LongPoll.Server", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, reply", + "arity": 2, + "function": "publish_reply", + "module": "Phoenix.Transports.LongPoll.Server" + } + }, + { + "caller": { + "function": "raise_route_error/6", + "line": 317, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, fun, arity, action, routes", + "arity": 5, + "function": "invalid_param_error", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "raise_route_error/6", + "line": 314, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "<<\"no function clause for \"::binary, Kernel.inspect(mod)::binary, \".\"::binary,\n String.Chars.to_string(fun)::binary, \"/\"::binary, String.Chars.to_string(arity)::binary,\n \" and action \"::binary, Kernel.inspect(action)::binary>>, fun, routes", + "arity": 3, + "function": "invalid_route_error", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "raise_route_error/6", + "line": 310, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "<<\"no action \"::binary, Kernel.inspect(action)::binary, \" for \"::binary,\n Kernel.inspect(mod)::binary, \".\"::binary, String.Chars.to_string(fun)::binary, \"/\"::binary,\n String.Chars.to_string(arity)::binary>>, fun, routes", + "arity": 3, + "function": "invalid_route_error", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "expand_segments/2", + "line": 366, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "[h], acc", + "arity": 2, + "function": "expand_segments", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "expand_segments/2", + "line": 371, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "t, {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n :elixir_quote.shallow_validate_ast(acc),\n :elixir_quote.shallow_validate_ast(<<\"/\"::binary, h::binary>>)\n ]}", + "arity": 2, + "function": "expand_segments", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "expand_segments/2", + "line": 375, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "t, {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n :elixir_quote.shallow_validate_ast(acc),\n {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n \"/\",\n {{:., [], [:elixir_quote.shallow_validate_ast(Phoenix.Router.Helpers), :encode_param]}, [],\n [{:to_param, [], [:elixir_quote.shallow_validate_ast(h)]}]}\n ]}\n ]}", + "arity": 2, + "function": "expand_segments", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "expand_segments/1", + "line": 355, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "segments, \"\"", + "arity": 2, + "function": "expand_segments", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "define/2", + "line": 29, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "defhelper_catch_all", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "define/2", + "line": 27, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route, exprs", + "arity": 2, + "function": "defhelper", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "defhelper/2", + "line": 256, + "module": "Phoenix.Router.Helpers", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "exprs.path()", + "arity": 1, + "function": "expand_segments", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "write_manifest/3", + "line": 116, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "save_manifest/4", + "line": 110, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "latest, digests, output_path", + "arity": 3, + "function": "write_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "save_manifest/4", + "line": 109, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "files", + "arity": 1, + "function": "generate_digests", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "remove_files/2", + "line": 403, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, output_path", + "arity": 2, + "function": "remove_compressed_file", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "remove_compressed_files/2", + "line": 408, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, output_path", + "arity": 2, + "function": "remove_compressed_file", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "remove_compressed_file/2", + "line": 412, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "compressed_extensions", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "relative_digested_path/2", + "line": 306, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digested_path", + "arity": 1, + "function": "relative_digested_path", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "relative_digested_path/2", + "line": 309, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digested_path", + "arity": 1, + "function": "relative_digested_path", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "maybe_fixup_sourcemap/2", + "line": 54, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "sourcemap, files", + "arity": 2, + "function": "fixup_sourcemap", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "load_manifest/1", + "line": 93, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "load_manifest/1", + "line": 94, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.json_library().decode!(File.read!(manifest_path)), output_path", + "arity": 2, + "function": "migrate_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "load_compile_digests/1", + "line": 83, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "output_path", + "arity": 1, + "function": "load_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "generate_latest/1", + "line": 77, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture.relative_path(), capture.digested_filename()", + "arity": 2, + "function": "manifest_join", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "generate_latest/1", + "line": 76, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture.relative_path(), capture.filename()", + "arity": 2, + "function": "manifest_join", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "generate_digests/1", + "line": 139, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture", + "arity": 1, + "function": "build_digest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "generate_digests/1", + "line": 138, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture.relative_path(), capture.digested_filename()", + "arity": 2, + "function": "manifest_join", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "fixup_sourcemaps/1", + "line": 49, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, files", + "arity": 2, + "function": "maybe_fixup_sourcemap", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "filter_files/1", + "line": 45, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, input_path", + "arity": 2, + "function": "map_file", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "filter_files/1", + "line": 44, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture", + "arity": 1, + "function": "compiled_file?", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "files_to_clean/4", + "line": 380, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "versions, max_age, keep", + "arity": 3, + "function": "versions_to_clean", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "files_to_clean/4", + "line": 379, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digests", + "arity": 1, + "function": "group_by_logical_path", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_url/4", + "line": 278, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digested_path, with_vsn?", + "arity": 2, + "function": "relative_digested_path", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_url/4", + "line": 294, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, digested_path, with_vsn?", + "arity": 3, + "function": "absolute_digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_url/4", + "line": 285, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "URI, %{scheme: nil, host: nil}", + "arity": 2, + "function": "%", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_contents/3", + "line": 237, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, latest", + "arity": 2, + "function": "digest_javascript_map_asset_references", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_contents/3", + "line": 236, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, latest", + "arity": 2, + "function": "digest_javascript_asset_references", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digested_contents/3", + "line": 235, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file, latest, with_vsn?", + "arity": 3, + "function": "digest_stylesheet_asset_references", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digest_stylesheet_asset_references/3", + "line": 255, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, file, latest, with_vsn?", + "arity": 4, + "function": "digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digest_stylesheet_asset_references/3", + "line": 252, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, file, latest, with_vsn?", + "arity": 4, + "function": "digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digest_javascript_map_asset_references/2", + "line": 272, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, file, latest, false", + "arity": 4, + "function": "digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "digest_javascript_asset_references/2", + "line": 264, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, file, latest, false", + "arity": 4, + "function": "digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compiled_file?/1", + "line": 161, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "compressed_extensions", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 33, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "capture, output_path", + "arity": 2, + "function": "write_to_disk", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 30, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "digested_files, latest, digests, output_path", + "arity": 4, + "function": "save_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 28, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "capture, latest, with_vsn?", + "arity": 3, + "function": "digested_contents", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 27, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "output_path", + "arity": 1, + "function": "load_compile_digests", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 26, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "files", + "arity": 1, + "function": "generate_latest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 25, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "files", + "arity": 1, + "function": "fixup_sourcemaps", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "compile/3", + "line": 24, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "input_path", + "arity": 1, + "function": "filter_files", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean_all/1", + "line": 369, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "remove_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean_all/1", + "line": 368, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "logical_paths, path", + "arity": 2, + "function": "remove_compressed_files", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean_all/1", + "line": 367, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "files, path", + "arity": 2, + "function": "remove_files", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean_all/1", + "line": 359, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "digests", + "arity": 1, + "function": "group_by_logical_path", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean_all/1", + "line": 358, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "load_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean/4", + "line": 340, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "latest, Map.drop(digests, files), path", + "arity": 3, + "function": "write_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean/4", + "line": 339, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "files, path", + "arity": 2, + "function": "remove_files", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean/4", + "line": 338, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "latest, digests, :erlang.-(now, age), keep", + "arity": 4, + "function": "files_to_clean", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean/4", + "line": 337, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "load_manifest", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "clean/3", + "line": 335, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "build_digest/1", + "line": 147, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "now", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "build_digest/1", + "line": 146, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file.relative_path(), file.filename()", + "arity": 2, + "function": "manifest_join", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "absolute_digested_url/3", + "line": 315, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, digested_path", + "arity": 2, + "function": "absolute_digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "absolute_digested_url/3", + "line": 318, + "module": "Phoenix.Digester", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, digested_path", + "arity": 2, + "function": "absolute_digested_url", + "module": "Phoenix.Digester" + } + }, + { + "caller": { + "function": "subscribe_and_join!/4", + "line": 371, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, channel, topic, payload", + "arity": 4, + "function": "subscribe_and_join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "subscribe_and_join!/3", + "line": 359, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, payload", + "arity": 4, + "function": "subscribe_and_join!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "subscribe_and_join!/2", + "line": 353, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, %{}", + "arity": 4, + "function": "subscribe_and_join!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "subscribe_and_join/4", + "line": 407, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, channel, topic, payload", + "arity": 4, + "function": "join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "subscribe_and_join/3", + "line": 385, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, payload", + "arity": 4, + "function": "subscribe_and_join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "subscribe_and_join/2", + "line": 379, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, %{}", + "arity": 4, + "function": "subscribe_and_join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "stringify_kv/1", + "line": 709, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "v", + "arity": 1, + "function": "__stringify__", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "socket/4", + "line": 236, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "socket_module, socket_id, socket_assigns, options, __CALLER__", + "arity": 5, + "function": "socket", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "socket/2", + "line": 301, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "nil, id, assigns, [], __CALLER__", + "arity": 5, + "function": "socket", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "socket/1", + "line": 209, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "socket_module, nil, [], [], __CALLER__", + "arity": 5, + "function": "socket", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "socket/0", + "line": 295, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "nil, nil, [], [], __CALLER__", + "arity": 5, + "function": "socket", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "push/3", + "line": 475, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "payload", + "arity": 1, + "function": "__stringify__", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "push/3", + "line": 475, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{join_ref: nil, event: event, topic: socket.topic(), ref: ref, payload: __stringify__(payload)}", + "arity": 2, + "function": "%", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "leave/1", + "line": 488, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, \"phx_leave\", %{}", + "arity": 3, + "function": "push", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/4", + "line": 454, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pid", + "arity": 1, + "function": "socket", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "join/4", + "line": 451, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "socket, channel, message, :erlang.++([starter: starter], opts)", + "arity": 4, + "function": "join", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "join/4", + "line": 444, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket, %{transport: {Phoenix.ChannelTest, sup}}", + "arity": 2, + "function": "%", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/4", + "line": 441, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, topic", + "arity": 2, + "function": "match_topic_to_channel!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/4", + "line": 432, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "payload", + "arity": 1, + "function": "__stringify__", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/4", + "line": 430, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{\n join_ref: nil,\n event: \"phx_join\",\n payload: __stringify__(payload),\n topic: topic,\n ref: :erlang.unique_integer([:positive])\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/3", + "line": 417, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, payload", + "arity": 4, + "function": "join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "join/2", + "line": 412, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, nil, topic, %{}", + "arity": 4, + "function": "join", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "close/2", + "line": 502, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "socket.channel_pid(), timeout", + "arity": 2, + "function": "close", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from!/3", + "line": 527, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, transport_pid, topic, event, message", + "arity": 5, + "function": "broadcast_from!", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "broadcast_from/3", + "line": 519, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "pubsub_server, transport_pid, topic, event, message", + "arity": 5, + "function": "broadcast_from", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "__stringify__/1", + "line": 702, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "stringify_kv", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__stringify__/1", + "line": 704, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "__stringify__", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__socket__/5", + "line": 264, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "options", + "arity": 1, + "function": "fetch_test_supervisor!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__socket__/5", + "line": 260, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "first_socket!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__socket__/5", + "line": 257, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket, %{\n channel: nil,\n channel_pid: nil,\n join_ref: nil,\n joined: false,\n private: %{},\n ref: nil,\n topic: nil,\n assigns: Enum.into(assigns, %{}),\n endpoint: endpoint,\n handler:\n case socket do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n first_socket!(endpoint)\n\n x ->\n x\n end,\n id: id,\n pubsub_server: endpoint.config(:pubsub_server),\n serializer: Phoenix.ChannelTest.NoopSerializer,\n transport: {Phoenix.ChannelTest, fetch_test_supervisor!(options)},\n transport_pid: :erlang.self()\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__connect__/4", + "line": 342, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "__stringify__", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "__connect__/4", + "line": 340, + "module": "Phoenix.ChannelTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "options", + "arity": 1, + "function": "fetch_test_supervisor!", + "module": "Phoenix.ChannelTest" + } + }, + { + "caller": { + "function": "warmup_static/2", + "line": 424, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digests, Map.get(latest, key), with_vsn?", + "arity": 3, + "function": "static_cache", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup_static/2", + "line": 423, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "endpoint, {:__phoenix_static__, <<\"/\"::binary, key::binary>>}, fn _ -> {:cache, static_cache(digests, Map.get(latest, key), with_vsn?)} end", + "arity": 3, + "function": "cache", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "warmup_static/2", + "line": 419, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "endpoint, :cache_static_manifest_latest, latest", + "arity": 3, + "function": "put", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "warmup_persistent/1", + "line": 378, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "case static_url_config[:path] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"/\"\n x -> x\nend", + "arity": 1, + "function": "empty_string_if_root", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup_persistent/1", + "line": 377, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, static_url_config", + "arity": 2, + "function": "build_url", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup_persistent/1", + "line": 374, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "case url_config[:path] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"/\"\n x -> x\nend", + "arity": 1, + "function": "empty_string_if_root", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup_persistent/1", + "line": 373, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "case url_config[:host] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"localhost\"\n x -> x\nend", + "arity": 1, + "function": "host_to_binary", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup_persistent/1", + "line": 372, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, url_config", + "arity": 2, + "function": "build_url", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup/1", + "line": 356, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, manifest", + "arity": 2, + "function": "warmup_static", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup/1", + "line": 355, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "cache_static_manifest", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "warmup/1", + "line": 352, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "warmup_persistent", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "static_lookup/2", + "line": 289, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "raise_invalid_path", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "static_lookup/2", + "line": 301, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "raise_invalid_path", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "static_cache/3", + "line": 434, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digests[value][\"sha512\"]", + "arity": 1, + "function": "static_integrity", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "static_cache/3", + "line": 438, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "digests[value][\"sha512\"]", + "arity": 1, + "function": "static_integrity", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "start_link/3", + "line": 17, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf", + "arity": 2, + "function": "browser_open", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "start_link/3", + "line": 16, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf", + "arity": 2, + "function": "log_access_url", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "socket_children/3", + "line": 142, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, fun, [:erlang.++([endpoint: endpoint], opts)]", + "arity": 3, + "function": "apply_or_ignore", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "socket_children/3", + "line": 141, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conf, opts", + "arity": 2, + "function": "check_origin_or_csrf_checked!", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "server?/2", + "line": 216, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Application.get_env(otp_app, endpoint, [])", + "arity": 1, + "function": "server?", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "port_to_integer/1", + "line": 313, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "System.get_env(env_var)", + "arity": 1, + "function": "port_to_integer", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "log_access_url/2", + "line": 469, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conf", + "arity": 1, + "function": "server?", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 108, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf, server?", + "arity": 3, + "function": "watcher_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 107, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf, :drainer_spec", + "arity": 3, + "function": "socket_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 106, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf, server?", + "arity": 3, + "function": "server_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 105, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf, :child_spec", + "arity": 3, + "function": "socket_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 104, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, conf", + "arity": 2, + "function": "pubsub_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 103, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod", + "arity": 1, + "function": "warmup_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 102, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, secret_conf, default_conf", + "arity": 3, + "function": "config_children", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 99, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, mod, conf, :static_url", + "arity": 4, + "function": "warn_on_deprecated_system_env_tuples", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 98, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, mod, conf, :url", + "arity": 4, + "function": "warn_on_deprecated_system_env_tuples", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 97, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, mod, conf, :https", + "arity": 4, + "function": "warn_on_deprecated_system_env_tuples", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 96, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, mod, conf, :http", + "arity": 4, + "function": "warn_on_deprecated_system_env_tuples", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 92, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "check_symlinks", + "module": "Phoenix.CodeReloader.Server" + } + }, + { + "caller": { + "function": "init/1", + "line": 83, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conf", + "arity": 1, + "function": "server?", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 30, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "otp_app, mod, default_conf", + "arity": 3, + "function": "from_env", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "init/1", + "line": 29, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "otp_app, mod", + "arity": 2, + "function": "defaults", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "init/1", + "line": 29, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "defaults(otp_app, mod), opts", + "arity": 2, + "function": "merge", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "host_to_binary/1", + "line": 309, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "System.get_env(env_var)", + "arity": 1, + "function": "host_to_binary", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "defaults/2", + "line": 232, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "render_errors", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "config_change/3", + "line": 271, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "warmup", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "config_change/3", + "line": 270, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "endpoint, changed, removed", + "arity": 3, + "function": "config_change", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "cache_static_manifest/1", + "line": 456, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "build_url/2", + "line": 415, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "URI, %{\n authority: nil,\n fragment: nil,\n path: nil,\n query: nil,\n userinfo: nil,\n scheme: scheme,\n port: port,\n host: host\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "build_url/2", + "line": 407, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "case url[:port] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> port\n x -> x\nend", + "arity": 1, + "function": "port_to_integer", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "build_url/2", + "line": 406, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "case url[:host] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"localhost\"\n x -> x\nend", + "arity": 1, + "function": "host_to_binary", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "browser_open/2", + "line": 475, + "module": "Phoenix.Endpoint.Supervisor", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conf", + "arity": 1, + "function": "server?", + "module": "Phoenix.Endpoint.Supervisor" + } + }, + { + "caller": { + "function": "validate_hosts!/1", + "line": 199, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "host", + "arity": 1, + "function": "raise_invalid_host", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "validate_hosts!/1", + "line": 205, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "invalid", + "arity": 1, + "function": "raise_invalid_host", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "update_stack/2", + "line": 282, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module, :phoenix_router_scopes, fun", + "arity": 3, + "function": "update_attribute", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "update_pipes/2", + "line": 286, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module, :phoenix_pipeline_scopes, fun", + "arity": 3, + "function": "update_attribute", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "update_attribute/3", + "line": 300, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module, attr", + "arity": 2, + "function": "get_attribute", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "route/8", + "line": 64, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "line, kind, verb, path, top.hosts(), alias, plug_opts, as, top.pipes(), private, assigns, metadata, trailing_slash?, warn_on_verify?", + "arity": 14, + "function": "build", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "route/8", + "line": 59, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path, plug", + "arity": 2, + "function": "validate_forward!", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "route/8", + "line": 50, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "top, path, plug, alias?, as, private, assigns", + "arity": 7, + "function": "join", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "route/8", + "line": 42, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts, top", + "arity": 2, + "function": "deprecated_trailing_slash", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "route/8", + "line": 40, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "plug, \"Controller\"", + "arity": 2, + "function": "resource_name", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "route/8", + "line": 37, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "validate_path", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "route/8", + "line": 36, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 138, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, [path: path]", + "arity": 2, + "function": "push", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 174, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts, top", + "arity": 2, + "function": "deprecated_trailing_slash", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 165, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Router.Scope, %{\n path: :erlang.++(top.path(), path),\n alias: alias,\n as: as,\n hosts: hosts,\n pipes: top.pipes(),\n private: :maps.merge(top.private(), private),\n assigns: :maps.merge(top.assigns(), assigns),\n log: Keyword.get(opts, :log, top.log()),\n trailing_slash?: deprecated_trailing_slash(opts, top)\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 165, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, %Phoenix.Router.Scope{\n path: :erlang.++(top.path(), path),\n alias: alias,\n as: as,\n hosts: hosts,\n pipes: top.pipes(),\n private: :maps.merge(top.private(), private),\n assigns: :maps.merge(top.assigns(), assigns),\n log: Keyword.get(opts, :log, top.log()),\n trailing_slash?: deprecated_trailing_slash(opts, top)\n}", + "arity": 2, + "function": "put_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 163, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, fn stack -> [top | stack] end", + "arity": 2, + "function": "update_stack", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 156, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "val", + "arity": 1, + "function": "validate_hosts!", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 152, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "top, opts, :as, fn capture -> capture end", + "arity": 4, + "function": "append_unless_false", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 151, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "top, opts, :alias, &:erlang.atom_to_binary/1", + "arity": 4, + "function": "append_unless_false", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 146, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path", + "arity": 1, + "function": "validate_path", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "push/2", + "line": 142, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "pop/1", + "line": 225, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, top", + "arity": 2, + "function": "put_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "pop/1", + "line": 224, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, fn [top | stack] ->\n put_top(module, top)\n stack\nend", + "arity": 2, + "function": "update_stack", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "pipeline/2", + "line": 115, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, fn capture -> MapSet.put(capture, pipe) end", + "arity": 2, + "function": "update_pipes", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "pipe_through/2", + "line": 131, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, %{top | pipes: :erlang.++(pipes, new_pipes)}", + "arity": 2, + "function": "put_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "pipe_through/2", + "line": 123, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "join/7", + "line": 259, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "top, as", + "arity": 2, + "function": "join_as", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "join/7", + "line": 259, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "top, path", + "arity": 2, + "function": "join_path", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "join/7", + "line": 254, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "top, alias", + "arity": 2, + "function": "join_alias", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "init/1", + "line": 24, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Router.Scope, %{\n alias: [],\n as: [],\n assigns: %{},\n hosts: [],\n log: :debug,\n path: [],\n pipes: [],\n private: %{},\n trailing_slash?: false\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "get_top/1", + "line": 278, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "module, :phoenix_top_scopes", + "arity": 2, + "function": "get_attribute", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "full_path/2", + "line": 247, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "full_path/2", + "line": 242, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "expand_alias/2", + "line": 234, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module", + "arity": 1, + "function": "get_top", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "expand_alias/2", + "line": 234, + "module": "Phoenix.Router.Scope", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "get_top(module), alias", + "arity": 2, + "function": "join_alias", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "verify_token/3", + "line": 262, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "endpoint, :erlang.atom_to_binary(endpoint.config(:pubsub_server)), signed, opts[:crypto]", + "arity": 4, + "function": "verify", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "transport_dispatch/4", + "line": 121, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "server_ref", + "arity": 1, + "function": "client_ref", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "transport_dispatch/4", + "line": 121, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:dispatch, client_ref(server_ref), body, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "status_token_messages_json/3", + "line": 287, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, %{\n \"status\" =>\n case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\n end,\n \"token\" => token,\n \"messages\" => messages\n}", + "arity": 2, + "function": "send_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "status_json/1", + "line": 283, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, %{\n \"status\" =>\n case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\n end\n}", + "arity": 2, + "function": "send_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "sign_token/3", + "line": 253, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "endpoint, :erlang.atom_to_binary(endpoint.config(:pubsub_server)), data, opts[:crypto]", + "arity": 4, + "function": "sign", + "module": "Phoenix.Token" + } + }, + { + "caller": { + "function": "send_json/2", + "line": 293, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 206, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "server_ref", + "arity": 1, + "function": "client_ref", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 206, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:subscribe, client_ref(server_ref), ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 205, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref", + "arity": 2, + "function": "subscribe", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 200, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref", + "arity": 2, + "function": "unsubscribe", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 196, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint.config(:endpoint_id), id, pid, priv_topic", + "arity": 4, + "function": "server_ref", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "resume_session/4", + "line": 194, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, token, opts", + "arity": 3, + "function": "verify_token", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "publish/4", + "line": 104, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_status(conn, status)", + "arity": 1, + "function": "status_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "publish/4", + "line": 98, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, msg, opts", + "arity": 4, + "function": "transport_dispatch", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "publish/4", + "line": 89, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "base64", + "arity": 1, + "function": "safe_decode64!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "new_session/4", + "line": 156, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_status(conn, :gone), token, []", + "arity": 3, + "function": "status_token_messages_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "new_session/4", + "line": 155, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, data, opts", + "arity": 3, + "function": "sign_token", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "new_session/4", + "line": 151, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_status(conn, :forbidden)", + "arity": 1, + "function": "status_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "new_session/4", + "line": 144, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "conn, endpoint, keys, Keyword.take(opts, [:check_csrf])", + "arity": 4, + "function": "connect_info", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "new_session/4", + "line": 141, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, opts[:auth_token]", + "arity": 2, + "function": "maybe_auth_token_from_header", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 188, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_status(conn, status), conn.params()[\"token\"], messages", + "arity": 3, + "function": "status_token_messages_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 182, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:expired, client_ref, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 177, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:expired, client_ref, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 171, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:flush, client_ref, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 163, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint, server_ref, {:flush, client_ref, ref}", + "arity": 3, + "function": "broadcast_from!", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "listen/4", + "line": 162, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "server_ref", + "arity": 1, + "function": "client_ref", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 58, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, endpoint, handler, opts", + "arity": 4, + "function": "new_session", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 55, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "new_conn, server_ref, endpoint, opts", + "arity": 4, + "function": "listen", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 53, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, conn.params(), endpoint, opts", + "arity": 4, + "function": "resume_session", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 69, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_status(conn, :gone)", + "arity": 1, + "function": "status_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 66, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "new_conn, server_ref, endpoint, opts", + "arity": 4, + "function": "publish", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "dispatch/4", + "line": 64, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, conn.params(), endpoint, opts", + "arity": 4, + "function": "resume_session", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "call/2", + "line": 31, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "status_json", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "call/2", + "line": 29, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Plug.Conn.put_resp_header(Plug.Conn.fetch_query_params(conn), \"access-control-allow-origin\", \"*\"), endpoint, opts", + "arity": 3, + "function": "code_reload", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 30, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n), opts[:transport_log]", + "arity": 2, + "function": "transport_log", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 31, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n ),\n opts[:transport_log]\n), handler, endpoint, opts, &status_json/1", + "arity": 5, + "function": "check_origin", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "call/2", + "line": 32, + "module": "Phoenix.Transports.LongPoll", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n ),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts,\n &status_json/1\n), endpoint, handler, opts", + "arity": 4, + "function": "dispatch", + "module": "Phoenix.Transports.LongPoll" + } + }, + { + "caller": { + "function": "phoenix_socket_connected/4", + "line": 363, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "filter_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_socket_connected/4", + "line": 357, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "duration", + "arity": 1, + "function": "duration", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_socket_connected/4", + "line": 354, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "result", + "arity": 1, + "function": "connect_result", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_router_dispatch_start/4", + "line": 324, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn.params()", + "arity": 1, + "function": "params", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_router_dispatch_start/4", + "line": 315, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "plug, plug_opts, 2", + "arity": 3, + "function": "mfa", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_router_dispatch_start/4", + "line": 314, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "mod, fun, arity", + "arity": 3, + "function": "mfa", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_router_dispatch_start/4", + "line": 304, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "level, conn", + "arity": 2, + "function": "log_level", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_error_rendered/4", + "line": 284, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "status", + "arity": 1, + "function": "status_to_string", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_error_rendered/4", + "line": 282, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "kind, reason", + "arity": 2, + "function": "error_banner", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_endpoint_stop/4", + "line": 263, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "duration", + "arity": 1, + "function": "duration", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_endpoint_stop/4", + "line": 263, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state", + "arity": 1, + "function": "connection_type", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_endpoint_stop/4", + "line": 262, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "status", + "arity": 1, + "function": "status_to_string", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_endpoint_stop/4", + "line": 255, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "metadata[:options][:log], conn", + "arity": 2, + "function": "log_level", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_endpoint_start/4", + "line": 241, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "metadata[:options][:log], conn", + "arity": 2, + "function": "log_level", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_joined/4", + "line": 405, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "filter_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_joined/4", + "line": 403, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "duration", + "arity": 1, + "function": "duration", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_joined/4", + "line": 400, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "result", + "arity": 1, + "function": "join_result", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_joined/4", + "line": 396, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":log_join, socket, fn ->\n %{result: result, params: params} = metadata\n\n [\n join_result(result),\n socket.topic(),\n \" in \",\n duration(duration),\n \"\\n Parameters: \",\n Kernel.inspect(filter_values(params))\n ]\nend", + "arity": 3, + "function": "channel_log", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_handled_in/4", + "line": 430, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "filter_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_handled_in/4", + "line": 428, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "duration", + "arity": 1, + "function": "duration", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "phoenix_channel_handled_in/4", + "line": 417, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":log_handle_in, socket, fn ->\n %{event: event, params: params} = metadata\n\n [\n \"HANDLED \",\n event,\n \" INCOMING ON \",\n socket.topic(),\n \" (\",\n Kernel.inspect(socket.channel()),\n \") in \",\n duration(duration),\n \"\\n Parameters: \",\n Kernel.inspect(filter_values(params))\n ]\nend", + "arity": 3, + "function": "channel_log", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "params/1", + "line": 336, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "filter_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "keep_values/2", + "line": 219, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "v, match", + "arity": 2, + "function": "keep_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "keep_values/2", + "line": 225, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, match", + "arity": 2, + "function": "keep_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 144, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_channel_handled_in", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 143, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_channel_joined", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 142, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_socket_drain", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 141, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_socket_connected", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 140, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_error_rendered", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 139, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_router_dispatch_start", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 138, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_endpoint_stop", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "install/0", + "line": 137, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 4, + "function": "phoenix_endpoint_start", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "filter_values/2", + "line": 183, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "values, match", + "arity": 2, + "function": "keep_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "filter_values/2", + "line": 182, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "values, key_match, value_match", + "arity": 3, + "function": "discard_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "filter_values/2", + "line": 181, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "filter", + "arity": 1, + "function": "compile_filter", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "discard_values/3", + "line": 201, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "v, key_match, value_match", + "arity": 3, + "function": "discard_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "discard_values/3", + "line": 207, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, key_match, value_match", + "arity": 3, + "function": "discard_values", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "compile_filter/1", + "line": 165, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "compile_discard", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "compile_filter/1", + "line": 167, + "module": "Phoenix.Logger", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "compile_discard", + "module": "Phoenix.Logger" + } + }, + { + "caller": { + "function": "web_app_name/1", + "line": 257, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Kernel.inspect(context.web_module())", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "validate_required_dependencies!/0", + "line": 275, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "generated_with_no_assets_or_esbuild?", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "validate_required_dependencies!/0", + "line": 272, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "\"mix phx.gen.auth requires phoenix_html\", :phx_generator_args", + "arity": 2, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "validate_required_dependencies!/0", + "line": 271, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "generated_with_no_html?", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "validate_required_dependencies!/0", + "line": 268, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "\"mix phx.gen.auth requires ecto_sql\", :phx_generator_args", + "arity": 2, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "validate_args!/1", + "line": 263, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "\"Invalid arguments\"", + "arity": 1, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 1034, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "ss", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 1034, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "mm", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 1034, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "hh", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 1034, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "d", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "timestamp/0", + "line": 1034, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "m", + "arity": 1, + "function": "pad", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "scope_config/3", + "line": 348, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, key, default_scope, assign_key", + "arity": 4, + "function": "scope_config_string", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "scope_config/3", + "line": 347, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, key, default_scope, assign_key", + "arity": 4, + "function": "new_scope", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "scope_config/3", + "line": 341, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, existing_scopes", + "arity": 2, + "function": "find_scope_name", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "scope_config/3", + "line": 336, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context.context_app()", + "arity": 1, + "function": "scopes_from_config", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "run/2", + "line": 240, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, binding, paths", + "arity": 3, + "function": "copy_new_files", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 241, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "copy_new_files(context, binding, paths), paths, binding", + "arity": 3, + "function": "inject_conn_case_helpers", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 242, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding), hashing_library", + "arity": 2, + "function": "inject_hashing_config", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 243, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n), binding", + "arity": 2, + "function": "maybe_inject_scope_config", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 244, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n), hashing_library", + "arity": 2, + "function": "maybe_inject_mix_dependency", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 245, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n), paths, binding", + "arity": 3, + "function": "inject_routes", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 246, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n), binding", + "arity": 2, + "function": "maybe_inject_router_import", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 247, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n), binding", + "arity": 2, + "function": "maybe_inject_router_plug", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 248, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n), binding", + "arity": 2, + "function": "maybe_inject_app_layout_menu", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 249, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n), paths, binding", + "arity": 3, + "function": "maybe_inject_agents_md", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 250, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "maybe_inject_agents_md(\n maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n ),\n paths,\n binding\n)", + "arity": 1, + "function": "maybe_print_mailer_installation_instructions", + "module": "Mix.Tasks.Phx.Gen.Notifier" + } + }, + { + "caller": { + "function": "run/2", + "line": 251, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Notifier.maybe_print_mailer_installation_instructions(\n maybe_inject_agents_md(\n maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(\n copy_new_files(context, binding, paths),\n paths,\n binding\n ),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n ),\n paths,\n binding\n )\n)", + "arity": 1, + "function": "print_shell_instructions", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 237, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 235, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "generator_paths", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "run/2", + "line": 231, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context, opts[:scope], Keyword.get(opts, :assign_key, \"current_scope\")", + "arity": 3, + "function": "scope_config", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 229, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "datetime_now", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 228, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "datetime_module", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 226, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ecto_adapter", + "arity": 1, + "function": "test_case_options", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 225, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "web_path_prefix", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 224, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "router_scope", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 219, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "web_app_name", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 212, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ecto_adapter", + "arity": 1, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Auth.Migration" + } + }, + { + "caller": { + "function": "run/2", + "line": 209, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "schema", + "arity": 1, + "function": "get_ecto_adapter!", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 202, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "validate_required_dependencies!", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 196, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "context", + "arity": 1, + "function": "prompt_for_code_injection", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/2", + "line": 195, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "put_live_option", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 193, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": ":erlang.++(context_args, [\"--no-scope\"]), [help_module: Mix.Tasks.Phx.Gen.Auth]", + "arity": 2, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "run/2", + "line": 185, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "build_hashing_library!", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 184, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "parsed", + "arity": 1, + "function": "validate_args!", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "run/2", + "line": 181, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "Mix.Tasks.Phx.Gen.Auth", + "arity": 1, + "function": "ensure_live_view_compat!", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "raise_with_help/1", + "line": 1068, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "msg, :general", + "arity": 2, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 432, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 433, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "files_to_be_generated(binding)", + "arity": 1, + "function": "prompt_for_conflicts", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "prompt_for_conflicts/1", + "line": 429, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "prompt_for_scope_conflicts", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "print_unable_to_read_file_error/2", + "line": 1062, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "<<\"\\nUnable to read file \"::binary,\n String.Chars.to_string(Path.relative_to_cwd(file_path))::binary, \".\\n\\n\"::binary,\n String.Chars.to_string(help_text)::binary, \"\\n\"::binary>>, 2", + "arity": 2, + "function": "indent_spaces", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "potential_layout_file_paths/1", + "line": 828, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new_scope/4", + "line": 394, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "key, %{\n default:\n case default_scope do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> true\n _ -> false\n end,\n module: Module.concat([context.module(), \"Scope\"]),\n assign_key: :erlang.binary_to_atom(assign_key),\n access_path: [\n :erlang.binary_to_atom(context.schema.singular()),\n case context.schema.opts()[:primary_key] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :id\n x -> x\n end\n ],\n schema_key:\n :erlang.binary_to_atom(\n < :id\n x -> x\n end\n )::binary>>\n ),\n schema_type:\n case context.schema.binary_id() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :id\n _ -> :binary_id\n end,\n schema_table: context.schema.table(),\n test_data_fixture: Module.concat([context.module(), \"Fixtures\"]),\n test_setup_helper:\n :erlang.binary_to_atom(\n <<\"register_and_log_in_\"::binary,\n String.Chars.to_string(context.schema.singular())::binary>>,\n :utf8\n )\n}", + "arity": 2, + "function": "new!", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "maybe_inject_scope_config/2", + "line": 872, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, binding", + "arity": 2, + "function": "inject_scope_config", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 771, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path, help_text", + "arity": 2, + "function": "print_unable_to_read_file_error", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 770, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 757, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path, \" - plug\"", + "arity": 2, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 756, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, binding", + "arity": 2, + "function": "router_plug_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 755, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "read_file", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 753, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file_path, binding", + "arity": 2, + "function": "router_plug_help_text", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_router_plug/2", + "line": 751, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 744, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path, help_text", + "arity": 2, + "function": "print_unable_to_read_file_error", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 743, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 730, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path, \" - imports\"", + "arity": 2, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 725, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, inject, fn capture, capture ->\n String.replace(\n capture,\n use_line,\n <>\n )\nend", + "arity": 3, + "function": "inject_unless_contains", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 723, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "read_file", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_router_import/2", + "line": 704, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "maybe_inject_mix_dependency/2", + "line": 680, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_mix_dependency/2", + "line": 678, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, mix_dependency", + "arity": 2, + "function": "mix_dependency_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_mix_dependency/2", + "line": 674, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app, \"mix.exs\"", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 790, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file_path, binding", + "arity": 2, + "function": "app_layout_menu_help_text", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 781, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 779, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "binding, File.read!(file_path)", + "arity": 2, + "function": "app_layout_menu_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 798, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "potential_layout_file_paths", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 794, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "binding", + "arity": 1, + "function": "app_layout_menu_code_to_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "maybe_inject_app_layout_menu/2", + "line": 778, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "get_layout_html_path", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_agents_md/3", + "line": 937, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "maybe_inject_agents_md/3", + "line": 927, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "File.cwd!()", + "arity": 1, + "function": "in_umbrella?", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "maybe_inject_agents_md/3", + "line": 922, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/AGENTS.md\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 632, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 633, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding)", + "arity": 1, + "function": "prepend_newline", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 634, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding)\n), test_file", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_tests/3", + "line": 629, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_test_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_scope_config/2", + "line": 897, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_scope_config/2", + "line": 895, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, scope_config", + "arity": 2, + "function": "config_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_scope_config/2", + "line": 890, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "read_file", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_scope_config/2", + "line": 882, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "File.cwd!()", + "arity": 1, + "function": "in_umbrella?", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_routes/3", + "line": 665, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/routes.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_routes/3", + "line": 666, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/routes.ex\", binding), file_path", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_routes/3", + "line": 661, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_hashing_config/2", + "line": 859, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file_path, hashing_library", + "arity": 2, + "function": "test_config_help_text", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_hashing_config/2", + "line": 852, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_hashing_config/2", + "line": 850, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, hashing_library", + "arity": 2, + "function": "test_config_inject", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_hashing_config/2", + "line": 845, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "read_file", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_hashing_config/2", + "line": 837, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "File.cwd!()", + "arity": 1, + "function": "in_umbrella?", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_context_test_fixtures/3", + "line": 645, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_context_test_fixtures/3", + "line": 646, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\", binding)", + "arity": 1, + "function": "prepend_newline", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_context_test_fixtures/3", + "line": 647, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "prepend_newline(\n Mix.Phoenix.eval_from(\n paths,\n \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\",\n binding\n )\n), test_fixtures_file", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_context_test_fixtures/3", + "line": 642, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_test_fixtures_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_context_functions/3", + "line": 623, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_context_functions/3", + "line": 624, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding)", + "arity": 1, + "function": "prepend_newline", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_context_functions/3", + "line": 625, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding)\n), file", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_context_functions/3", + "line": 620, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "ensure_context_file_exists", + "module": "Mix.Tasks.Phx.Gen.Context" + } + }, + { + "caller": { + "function": "inject_conn_case_helpers/3", + "line": 654, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth/conn_case.exs\", binding", + "arity": 3, + "function": "eval_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "inject_conn_case_helpers/3", + "line": 655, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/conn_case.exs\", binding), test_file", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 1010, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "content_to_inject, 2", + "arity": 2, + "function": "indent_spaces", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 1003, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path, <<\"\\nPlease add the following to the end of your equivalent\\n\"::binary,\n String.Chars.to_string(Path.relative_to_cwd(file_path))::binary, \" module:\\n\\n\"::binary,\n String.Chars.to_string(indent_spaces(content_to_inject, 2))::binary, \"\\n\"::binary>>", + "arity": 2, + "function": "print_unable_to_read_file_error", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 1001, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 994, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "print_injecting", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 993, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "file, content_to_inject", + "arity": 2, + "function": "inject_before_final_end", + "module": "Mix.Tasks.Phx.Gen.Auth.Injector" + } + }, + { + "caller": { + "function": "inject_before_final_end/2", + "line": 992, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "file_path", + "arity": 1, + "function": "read_file", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "get_layout_html_path/1", + "line": 823, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context", + "arity": 1, + "function": "potential_layout_file_paths", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "find_scope_name/2", + "line": 371, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "existing_scopes, <>", + "arity": 2, + "function": "is_new_scope?", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "find_scope_name/2", + "line": 367, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "existing_scopes, <>", + "arity": 2, + "function": "is_new_scope?", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "find_scope_name/2", + "line": 363, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "existing_scopes, context.schema.singular()", + "arity": 2, + "function": "is_new_scope?", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 601, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":erlang.++(default_files, non_live_files)", + "arity": 1, + "function": "remap_files", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 562, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": ":erlang.++(default_files, live_files)", + "arity": 1, + "function": "remap_files", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 493, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "timestamp", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 487, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context_app, \"priv/repo/migrations\"", + "arity": 2, + "function": "context_app_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 486, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_test_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "files_to_be_generated/1", + "line": 485, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "context_app", + "arity": 1, + "function": "web_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 614, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_context_test_fixtures", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 613, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_tests", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 612, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "context, paths, binding", + "arity": 3, + "function": "inject_context_functions", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 611, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "paths, \"priv/templates/phx.gen.auth\", binding, files", + "arity": 4, + "function": "copy_from", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "copy_new_files/3", + "line": 610, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "binding", + "arity": 1, + "function": "files_to_be_generated", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "build_hashing_library!/1", + "line": 321, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "<<\"Unknown value for --hashing-lib \"::binary, Kernel.inspect(unknown_library)::binary>>, :hashing_lib", + "arity": 2, + "function": "raise_with_help", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "build_hashing_library!/1", + "line": 314, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "default_hashing_library_option", + "module": "Mix.Tasks.Phx.Gen.Auth" + } + }, + { + "caller": { + "function": "build_hashing_library!/1", + "line": 315, + "module": "Mix.Tasks.Phx.Gen.Auth", + "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "Keyword.get_lazy(opts, :hashing_lib, &default_hashing_library_option/0)", + "arity": 1, + "function": "build", + "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" + } + }, + { + "caller": { + "function": "origin_allowed?/4", + "line": 623, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint.config(:url)[:host]", + "arity": 1, + "function": "host_to_binary", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "origin_allowed?/4", + "line": 623, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "uri.host(), host_to_binary(endpoint.config(:url)[:host])", + "arity": 2, + "function": "compare?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "origin_allowed?/4", + "line": 626, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "uri, check_origin", + "arity": 2, + "function": "origin_allowed?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "origin_allowed?/2", + "line": 634, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "origin_host, allowed_host", + "arity": 2, + "function": "compare_host?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "origin_allowed?/2", + "line": 633, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "origin_port, allowed_port", + "arity": 2, + "function": "compare?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "origin_allowed?/2", + "line": 632, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "origin_scheme, allowed_scheme", + "arity": 2, + "function": "compare?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "load_config/2", + "line": 256, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Keyword.merge(module.default_config(), config)", + "arity": 1, + "function": "load_config", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "load_config/1", + "line": 276, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "session", + "arity": 1, + "function": "init_session", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "host_to_binary/1", + "line": 652, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "System.get_env(env_var)", + "arity": 1, + "function": "host_to_binary", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "fetch_uri/1", + "line": 548, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "URI, %{\n fragment: nil,\n userinfo: nil,\n scheme: String.Chars.to_string(conn.scheme()),\n query: conn.query_string(),\n port: conn.port(),\n host: conn.host(),\n authority: conn.host(),\n path: conn.request_path()\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_session/4", + "line": 517, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, session, csrf_token_key", + "arity": 3, + "function": "csrf_token_valid?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_session/4", + "line": 527, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "session_config", + "arity": 1, + "function": "init_session", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_session/4", + "line": 527, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, endpoint, init_session(session_config), opts", + "arity": 4, + "function": "connect_session", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 499, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, endpoint, session, opts", + "arity": 4, + "function": "connect_session", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 496, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, \"sec-websocket-\"", + "arity": 2, + "function": "fetch_headers", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 493, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "fetch_user_agent", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 490, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "fetch_uri", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 487, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, \"x-\"", + "arity": 2, + "function": "fetch_headers", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "connect_info/4", + "line": 484, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "fetch_trace_context_headers", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "code_reload/3", + "line": 309, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "endpoint", + "arity": 1, + "function": "reload", + "module": "Phoenix.CodeReloader" + } + }, + { + "caller": { + "function": "check_subprotocols/2", + "line": 416, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, subprotocols", + "arity": 2, + "function": "subprotocols_error_response", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "check_subprotocols/2", + "line": 421, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, subprotocols", + "arity": 2, + "function": "subprotocols_error_response", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "check_origin_config/3", + "line": 577, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "parse_origin", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "check_origin_config/3", + "line": 573, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "endpoint, {:check_origin, handler}, fn _ ->\n check_origin =\n case Keyword.get(opts, :check_origin, endpoint.config(:check_origin)) do\n origins when :erlang.is_list(origins) ->\n Enum.map(origins, &parse_origin/1)\n\n boolean when :erlang.is_boolean(boolean) ->\n boolean\n\n {module, function, arguments} ->\n {module, function, arguments}\n\n :conn ->\n :conn\n\n invalid ->\n :erlang.error(\n ArgumentError.exception(\n <<\":check_origin expects a boolean, list of hosts, :conn, or MFA tuple, got: \"::binary,\n Kernel.inspect(invalid)::binary>>\n )\n )\n end\n\n {:cache, check_origin}\nend", + "arity": 3, + "function": "cache", + "module": "Phoenix.Config" + } + }, + { + "caller": { + "function": "check_origin/5", + "line": 352, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "check_origin, URI.parse(origin), endpoint, conn", + "arity": 4, + "function": "origin_allowed?", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "check_origin/5", + "line": 346, + "module": "Phoenix.Socket.Transport", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "handler, endpoint, opts", + "arity": 3, + "function": "check_origin_config", + "module": "Phoenix.Socket.Transport" + } + }, + { + "caller": { + "function": "value/3", + "line": 287, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Keyword.fetch!(schema.types(), field), value", + "arity": 2, + "function": "inspect_value", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "types/1", + "line": 513, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "val", + "arity": 1, + "function": "schema_type", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "types/1", + "line": 512, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "val", + "arity": 1, + "function": "schema_type", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "types/1", + "line": 511, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "vals", + "arity": 1, + "function": "translate_enum_vals", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 360, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_naive_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 357, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_naive_datetime", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 350, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 342, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_datetime", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 335, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Time, %{calendar: Calendar.ISO, hour: 14, minute: 0, second: 0, microsecond: {0, 6}}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 332, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Time, %{calendar: Calendar.ISO, hour: 14, minute: 0, second: 0, microsecond: {0, 0}}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 308, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "values, :create", + "arity": 2, + "function": "build_enum_values", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 305, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "type, :create", + "arity": 2, + "function": "build_array_values", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 384, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_naive_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 383, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_naive_datetime", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 382, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 381, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_datetime", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 379, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Time, %{calendar: Calendar.ISO, hour: 15, minute: 1, second: 1, microsecond: {0, 6}}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 378, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Time, %{calendar: Calendar.ISO, hour: 15, minute: 1, second: 1, microsecond: {0, 0}}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 370, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "values, :update", + "arity": 2, + "function": "build_enum_values", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "type_to_default/3", + "line": 369, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "type, :update", + "arity": 2, + "function": "build_array_values", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "split_flags/5", + "line": 186, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, name, attrs, [name | uniques], redacts", + "arity": 5, + "function": "split_flags", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "split_flags/5", + "line": 189, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, name, attrs, uniques, [name | redacts]", + "arity": 5, + "function": "split_flags", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "partition_attrs_and_assocs/3", + "line": 477, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "key", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "partition_attrs_and_assocs/3", + "line": 473, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "scope, key_id", + "arity": 2, + "function": "validate_scope_and_reference_conflict!", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "params/2", + "line": 210, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "k, t, action", + "arity": 3, + "function": "type_to_default", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 158, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs, fixture_unique_functions", + "arity": 2, + "function": "fixture_params", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 156, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "migration_module", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 153, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "sample_id", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 151, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "web_path, schema_plural", + "arity": 2, + "function": "route_prefix", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 150, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "web_path, singular", + "arity": 2, + "function": "route_helper", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 145, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs, :update", + "arity": 2, + "function": "params", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 141, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs", + "arity": 1, + "function": "migration_defaults", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 138, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema_plural", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 137, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "singular", + "arity": 1, + "function": "humanize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 136, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "table, assocs, uniques", + "arity": 3, + "function": "indexes", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 133, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs", + "arity": 1, + "function": "schema_defaults", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 116, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Mix.Phoenix.Schema, %{\n opts: opts,\n migration?: Keyword.get(opts, :migration, true),\n module: module,\n repo: repo,\n repo_alias: repo_alias,\n table: table,\n embedded?: embedded?,\n alias: Module.concat(List.last(Module.split(module)), nil),\n file: file,\n attrs: attrs,\n plural: schema_plural,\n singular: singular,\n collection: collection,\n optionals: optionals,\n assocs: assocs,\n types: types,\n defaults: schema_defaults(attrs),\n uniques: uniques,\n redacts: redacts,\n indexes: indexes(table, assocs, uniques),\n human_singular: Phoenix.Naming.humanize(singular),\n human_plural: Phoenix.Naming.humanize(schema_plural),\n binary_id: opts[:binary_id],\n timestamp_type:\n case opts[:timestamp_type] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :naive_datetime\n x -> x\n end,\n migration_defaults: migration_defaults(attrs),\n string_attr: string_attr,\n params: %{\n create: create_params,\n update: params(attrs, :update),\n default_key:\n case string_attr do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n default_params_key\n\n x ->\n x\n end\n },\n web_namespace: web_namespace,\n web_path: web_path,\n route_helper: route_helper(web_path, singular),\n route_prefix: route_prefix(web_path, schema_plural),\n api_route_prefix: api_prefix,\n sample_id: sample_id(opts),\n context_app: ctx_app,\n generate?: generate?,\n migration_module: migration_module(),\n fixture_unique_functions: Enum.sort(fixture_unique_functions),\n fixture_params: fixture_params(attrs, fixture_unique_functions),\n prefix: opts[:prefix],\n scope: scope\n}", + "arity": 2, + "function": "%", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 114, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "singular, uniques, attrs", + "arity": 3, + "function": "fixture_unique_functions", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 104, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs, :create", + "arity": 2, + "function": "params", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 103, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "types", + "arity": 1, + "function": "string_attr", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 100, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "List.last(Module.split(module))", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 91, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "web_namespace", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 90, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "opts[:web]", + "arity": 1, + "function": "camelize", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 89, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "attrs", + "arity": 1, + "function": "types", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 88, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "cli_attrs", + "arity": 1, + "function": "attrs", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 88, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "module, attrs(cli_attrs), scope", + "arity": 3, + "function": "partition_attrs_and_assocs", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 87, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "cli_attrs", + "arity": 1, + "function": "extract_attr_flags", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "new/4", + "line": 86, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, opts[:scope], opts[:no_scope]", + "arity": 3, + "function": "scope_from_opts", + "module": "Mix.Phoenix.Scope" + } + }, + { + "caller": { + "function": "new/4", + "line": 84, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app, <>", + "arity": 2, + "function": "context_lib_path", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/4", + "line": 80, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "schema_name", + "arity": 1, + "function": "underscore", + "module": "Phoenix.Naming" + } + }, + { + "caller": { + "function": "new/4", + "line": 79, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "ctx_app", + "arity": 1, + "function": "context_base", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/4", + "line": 77, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "otp_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "new/4", + "line": 76, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "context_app", + "module": "Mix.Phoenix" + } + }, + { + "caller": { + "function": "format_fields_for_schema/1", + "line": 261, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Enum.member?(schema.redacts(), k)", + "arity": 1, + "function": "maybe_redact_field", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "format_fields_for_schema/1", + "line": 261, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "v", + "arity": 1, + "function": "type_and_opts_for_schema", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "fixture_params/2", + "line": 628, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "attr, type, :create", + "arity": 3, + "function": "type_to_default", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "extract_attr_flags/1", + "line": 179, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Enum.reverse(rest), attr_name, attrs, uniques, redacts", + "arity": 5, + "function": "split_flags", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "build_utc_naive_datetime/0", + "line": 422, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_naive_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "build_utc_datetime/0", + "line": 416, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_utc_datetime_usec", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "build_enum_values/2", + "line": 405, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "values", + "arity": 1, + "function": "translate_enum_vals", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "attrs/1", + "line": 201, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "String.split(attr, \":\", parts: 3)", + "arity": 1, + "function": "list_to_attr", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "attrs/1", + "line": 202, + "module": "Mix.Phoenix.Schema", + "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "list_to_attr(String.split(attr, \":\", parts: 3))", + "arity": 1, + "function": "validate_attr!", + "module": "Mix.Phoenix.Schema" + } + }, + { + "caller": { + "function": "text_response/2", + "line": 403, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :text", + "arity": 2, + "function": "response_content_type", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "text_response/2", + "line": 402, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, status", + "arity": 2, + "function": "response", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "response_content_type?/2", + "line": 327, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "header", + "arity": 1, + "function": "parse_content_type", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "response_content_type/2", + "line": 316, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "h, format", + "arity": 2, + "function": "response_content_type?", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "redirected_to/2", + "line": 445, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, Plug.Conn.Status.code(status)", + "arity": 2, + "function": "redirected_to", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 597, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "[conn: conn, router: router]", + "arity": 1, + "function": "exception", + "module": "Phoenix.Router.NoRouteError" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 595, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router, \"GET\", path, case host do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> conn.host()\n x -> x\nend", + "arity": 4, + "function": "route_info", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 593, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, router, path", + "arity": 3, + "function": "remove_script_name", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 592, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, status", + "arity": 2, + "function": "redirected_to", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 592, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "URI, %{path: path, host: host}", + "arity": 2, + "function": "%", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "redirected_params/2", + "line": 591, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "router_module", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "recycle/2", + "line": 477, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "build_conn", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "recycle/2", + "line": 482, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Test.put_peer_data(\n Plug.Test.recycle_cookies(\n :maps.put(:remote_ip, conn.remote_ip(), :maps.put(:host, conn.host(), build_conn())),\n conn\n ),\n Plug.Conn.get_peer_data(conn)\n), conn.req_headers(), headers", + "arity": 3, + "function": "copy_headers", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "put_flash/3", + "line": 293, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn, key, value", + "arity": 3, + "function": "put_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "path_params/2", + "line": 634, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "[conn: conn, router: router]", + "arity": 1, + "function": "exception", + "module": "Phoenix.Router.NoRouteError" + } + }, + { + "caller": { + "function": "path_params/2", + "line": 629, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router, \"GET\", to, conn.host()", + "arity": 4, + "function": "route_info", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "path_params/2", + "line": 627, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "router_module", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "json_response/2", + "line": 422, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "json_response/2", + "line": 420, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :json", + "arity": 2, + "function": "response_content_type", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "json_response/2", + "line": 419, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, status", + "arity": 2, + "function": "response", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "html_response/2", + "line": 388, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :html", + "arity": 2, + "function": "response_content_type", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "html_response/2", + "line": 387, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, status", + "arity": 2, + "function": "response", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "get_flash/2", + "line": 286, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn.assigns.flash(), key", + "arity": 2, + "function": "get", + "module": "Phoenix.Flash" + } + }, + { + "caller": { + "function": "fetch_flash/1", + "line": 271, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "fetch_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "ensure_recycled/1", + "line": 500, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "recycle", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "dispatch/5", + "line": 224, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "ensure_recycled", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "dispatch/5", + "line": 225, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "ensure_recycled(conn), endpoint, method, path_or_action, params_or_body", + "arity": 5, + "function": "dispatch_endpoint", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "dispatch/5", + "line": 227, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_private(\n dispatch_endpoint(ensure_recycled(conn), endpoint, method, path_or_action, params_or_body),\n :phoenix_recycled,\n false\n)", + "arity": 1, + "function": "from_set_to_sent", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "discard_previously_sent/0", + "line": 720, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "discard_previously_sent", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "discard_previously_sent/0", + "line": 719, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "discard_previously_sent", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "clear_flash/1", + "line": 299, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn", + "arity": 1, + "function": "clear_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "build_conn/3", + "line": 152, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Conn, %{\n adapter: {Plug.MissingAdapter, nil},\n assigns: %{},\n body_params: %{__struct__: Plug.Conn.Unfetched, aspect: :body_params},\n cookies: %{__struct__: Plug.Conn.Unfetched, aspect: :cookies},\n halted: false,\n host: \"www.example.com\",\n method: \"GET\",\n owner: nil,\n params: %{__struct__: Plug.Conn.Unfetched, aspect: :params},\n path_info: [],\n path_params: %{},\n port: 0,\n private: %{},\n query_params: %{__struct__: Plug.Conn.Unfetched, aspect: :query_params},\n query_string: \"\",\n remote_ip: nil,\n req_cookies: %{__struct__: Plug.Conn.Unfetched, aspect: :cookies},\n req_headers: [],\n request_path: \"\",\n resp_body: nil,\n resp_cookies: %{},\n resp_headers: [{\"cache-control\", \"max-age=0, private, must-revalidate\"}],\n scheme: :http,\n script_name: [],\n secret_key_base: nil,\n state: :unset,\n status: nil\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "build_conn/0", + "line": 140, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": ":get, \"/\", nil", + "arity": 3, + "function": "build_conn", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "assert_error_sent/2", + "line": 685, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "discard_previously_sent", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "assert_error_sent/2", + "line": 682, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "func", + "arity": 1, + "function": "wrap_request", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "assert_error_sent/2", + "line": 683, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "wrap_request(func), expected_status", + "arity": 2, + "function": "receive_response", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "assert_error_sent/2", + "line": 679, + "module": "Phoenix.ConnTest", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "discard_previously_sent", + "module": "Phoenix.ConnTest" + } + }, + { + "caller": { + "function": "user_connect/6", + "line": 653, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "set_label", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "user_connect/6", + "line": 646, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket, %{}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "user_connect/6", + "line": 624, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket, %{\n assigns: %{},\n channel: nil,\n channel_pid: nil,\n id: nil,\n join_ref: nil,\n joined: false,\n private: %{},\n ref: nil,\n topic: nil,\n transport_pid: nil,\n handler: handler,\n endpoint: endpoint,\n pubsub_server: endpoint.config(:pubsub_server),\n serializer: serializer,\n transport: transport\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "socket_close/2", + "line": 873, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, topic, join_ref", + "arity": 3, + "function": "encode_close", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "socket_close/2", + "line": 872, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state, pid, topic, monitor_ref", + "arity": 4, + "function": "delete_channel", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 692, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 685, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{join_ref: nil, ref: ref, topic: \"phoenix\", status: :ok, payload: %{}}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 730, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, message", + "arity": 2, + "function": "encode_ignore", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 725, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 717, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{join_ref: join_ref, ref: ref, topic: topic, status: :error, payload: reply}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 714, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 713, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state, pid, topic, join_ref", + "arity": 4, + "function": "put_channel", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 705, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{join_ref: join_ref, ref: ref, topic: topic, status: :ok, payload: reply}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 703, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "socket, channel, message, opts", + "arity": 4, + "function": "join", + "module": "Phoenix.Channel.Server" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 750, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "nil, message, new_state, new_socket", + "arity": 4, + "function": "handle_in", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 748, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "pid, {state, socket}", + "arity": 2, + "function": "socket_close", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 747, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "pid", + "arity": 1, + "function": "shutdown_duplicate_channel", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 760, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "state, pid, topic, :leaving", + "arity": 4, + "function": "update_channel_status", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 797, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 789, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{ref: ref, join_ref: join_ref, topic: topic, status: :ok, payload: %{}}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "handle_in/4", + "line": 803, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, message", + "arity": 2, + "function": "encode_ignore", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_on_exit/4", + "line": 830, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, message", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_on_exit/4", + "line": 829, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{join_ref: ref, ref: ref, topic: topic, event: \"phx_error\", payload: %{}}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_ignore/2", + "line": 835, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, reply", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_ignore/2", + "line": 834, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Reply, %{join_ref: nil, ref: ref, topic: topic, status: :error, payload: %{reason: \"unmatched topic\"}}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_close/3", + "line": 852, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "socket, message", + "arity": 2, + "function": "encode_reply", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "encode_close/3", + "line": 844, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.Socket.Message, %{join_ref: join_ref, ref: join_ref, topic: topic, event: \"phx_close\", payload: %{}}", + "arity": 2, + "function": "%", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "channel/3", + "line": 402, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "channel/3", + "line": 398, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "module, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "assign/3", + "line": 343, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, [{key, value}]", + "arity": 2, + "function": "assign", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "assign/2", + "line": 368, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, fun.(socket.assigns())", + "arity": 2, + "function": "assign", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__init__/1", + "line": 537, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket", + "arity": 1, + "function": "set_label", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__info__/2", + "line": 551, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "socket, topic, join_ref, reason", + "arity": 4, + "function": "encode_on_exit", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__info__/2", + "line": 550, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "state, pid, topic, ref", + "arity": 4, + "function": "delete_channel", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__info__/2", + "line": 572, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "pid, state", + "arity": 2, + "function": "socket_close", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__in__/2", + "line": 544, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Map.get(state.channels(), topic), message, state, socket", + "arity": 4, + "function": "handle_in", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__connect__/3", + "line": 514, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "result", + "arity": 1, + "function": "result", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__connect__/3", + "line": 504, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "user_socket, endpoint, transport, serializer, params, connect_info", + "arity": 6, + "function": "user_connect", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__connect__/3", + "line": 502, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Keyword.fetch!(options, :serializer), vsn", + "arity": 2, + "function": "negotiate_serializer", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 432, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "topic_pattern", + "arity": 1, + "function": "to_topic_match", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 433, + "module": "Phoenix.Socket", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "to_topic_match(topic_pattern), module, opts", + "arity": 3, + "function": "defchannel", + "module": "Phoenix.Socket" + } + }, + { + "caller": { + "function": "trace/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "trace/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :trace, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scoped_path/2", + "line": 1181, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router_module, path", + "arity": 2, + "function": "full_path", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "scoped_alias/2", + "line": 1173, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "router_module, alias", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router.Scope" + } + }, + { + "caller": { + "function": "scope/4", + "line": 1144, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "options, context", + "arity": 2, + "function": "do_scope", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scope/4", + "line": 1135, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "alias, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scope/3", + "line": 1115, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "options, context", + "arity": 2, + "function": "do_scope", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scope/3", + "line": 1100, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scope/2", + "line": 1078, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "options, context", + "arity": 2, + "function": "do_scope", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "scope/2", + "line": 1073, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "route_info/4", + "line": 1264, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "router, method, split_path, host", + "arity": 4, + "function": "route_info", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "resources/4", + "line": 1000, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "path, controller, opts, [do: nested_context]", + "arity": 4, + "function": "add_resources", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "resources/3", + "line": 1007, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "path, controller, [], [do: nested_context]", + "arity": 4, + "function": "add_resources", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "resources/3", + "line": 1011, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "path, controller, opts, [do: nil]", + "arity": 4, + "function": "add_resources", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "resources/2", + "line": 1018, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "path, controller, [], [do: nil]", + "arity": 4, + "function": "add_resources", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "put/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "put/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :put, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "post/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "post/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :post, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "plug/2", + "line": 829, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, opts, __CALLER__", + "arity": 3, + "function": "expand_plug_and_opts", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "pipe_through/1", + "line": 907, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "pipe_through/1", + "line": 906, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "plug_init_mode", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "patch/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "patch/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :patch, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "options/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "options/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :options, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "match/5", + "line": 710, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "match/5", + "line": 710, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, verb, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "head/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "head/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :head, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "get/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "get/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :get, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "forward/4", + "line": 1221, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":forward, :*, path, plug, plug_opts, router_opts", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "forward/4", + "line": 1217, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, plug_opts, __CALLER__", + "arity": 3, + "function": "expand_plug_and_opts", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "expand_plug_and_opts/3", + "line": 852, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "capture, caller", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "expand_plug_and_opts/3", + "line": 845, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "plug, caller", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "expand_plug_and_opts/3", + "line": 841, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "plug_init_mode", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "delete/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "delete/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :delete, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "connect/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "connect/4", + "line": 734, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": ":match, :connect, path, expand_alias(plug, __CALLER__), plug_opts, options", + "arity": 6, + "function": "add_route", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "build_pipes/2", + "line": 665, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "plug_init_mode", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "build_match_pipes/3", + "line": 630, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "name, pipe_through", + "arity": 2, + "function": "build_pipes", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "build_match/2", + "line": 610, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "route, path_params", + "arity": 2, + "function": "build_metadata", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "build_match/2", + "line": 595, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "route, acc_pipes, known_pipes", + "arity": 3, + "function": "build_match_pipes", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 293, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "verified_routes", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 292, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "match_dispatch", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 291, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 0, + "function": "defs", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 290, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "prelude", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__call__/5", + "line": 414, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Conn, %{}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__call__/5", + "line": 408, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Conn, %{halted: true}", + "arity": 2, + "function": "%", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 508, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, routes_per_path", + "arity": 2, + "function": "build_verify", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 498, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "", + "arity": 2, + "function": "build_match", + "module": "Phoenix.Router" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 494, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "remote", + "callee": { + "args": "env, routes_with_exprs", + "arity": 2, + "function": "define", + "module": "Phoenix.Router.Helpers" + } + }, + { + "caller": { + "function": "__before_compile__/1", + "line": 490, + "module": "Phoenix.Router", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "kind": "defmacro" + }, + "type": "remote", + "callee": { + "args": "capture", + "arity": 1, + "function": "exprs", + "module": "Phoenix.Router.Route" + } + }, + { + "caller": { + "function": "verify_segment/3", + "line": 765, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [\"/\" | acc]", + "arity": 3, + "function": "verify_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_segment/3", + "line": 775, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "dynamic_query, route, [static_query]", + "arity": 3, + "function": "verify_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_segment/3", + "line": 771, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [URI.encode(segment) | acc]", + "arity": 3, + "function": "verify_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_segment/3", + "line": 786, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [static_query_segment]", + "arity": 3, + "function": "verify_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_segment/3", + "line": 804, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [rewrite | acc]", + "arity": 3, + "function": "verify_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_segment/2", + "line": 758, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "segments, route, []", + "arity": 3, + "function": "verify_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_query/3", + "line": 833, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [rewrite | acc]", + "arity": 3, + "function": "verify_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_query/3", + "line": 839, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [\"=\" | acc]", + "arity": 3, + "function": "verify_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_query/3", + "line": 848, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest, route, [param | acc]", + "arity": 3, + "function": "verify_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "verify_query/3", + "line": 852, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "route", + "arity": 1, + "function": "raise_invalid_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/3", + "line": 565, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/3", + "line": 566, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", + "arity": 2, + "function": "inject_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/3", + "line": 569, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "other", + "arity": 1, + "function": "raise_invalid_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/2", + "line": 546, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/2", + "line": 547, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", + "arity": 2, + "function": "inject_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/2", + "line": 543, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :router", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/2", + "line": 550, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "other", + "arity": 1, + "function": "raise_invalid_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/1", + "line": 528, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, sigil_p, __CALLER__, endpoint, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/1", + "line": 529, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, sigil_p, __CALLER__, endpoint, router), __CALLER__", + "arity": 2, + "function": "inject_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/1", + "line": 525, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :router", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/1", + "line": 524, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :endpoint", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "url/1", + "line": 532, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "other", + "arity": 1, + "function": "raise_invalid_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_url/3", + "line": 623, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn_or_socket_or_endpoint_or_uri, path, params", + "arity": 3, + "function": "guarded_unverified_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 714, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "path, conn.script_name()", + "arity": 2, + "function": "path_with_script", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 713, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, router, path", + "arity": 3, + "function": "build_conn_forward_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 712, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, router, path", + "arity": 3, + "function": "build_own_forward_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 715, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "case (case build_own_forward_path(conn, router, path) do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n build_conn_forward_path(conn, router, path)\n\n x ->\n x\n end) do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n path_with_script(path, conn.script_name())\n\n x ->\n x\nend, params", + "arity": 2, + "function": "append_params", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 719, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "< \"\"\n x -> x\n end::binary, path::binary>>, params", + "arity": 2, + "function": "append_params", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 723, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, router, path, params", + "arity": 4, + "function": "unverified_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "unverified_path/4", + "line": 727, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint.path(path), params", + "arity": 2, + "function": "append_params", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "to_param/1", + "line": 912, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "data", + "arity": 1, + "function": "to_param", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "static_url/2", + "line": 592, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, path", + "arity": 2, + "function": "static_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "static_url/2", + "line": 591, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "static_url, path", + "arity": 2, + "function": "concat_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "static_url/2", + "line": 597, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, path", + "arity": 2, + "function": "static_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "static_path/2", + "line": 690, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, path", + "arity": 2, + "function": "static_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "static_integrity/2", + "line": 879, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, path", + "arity": 2, + "function": "static_integrity", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "static_integrity/2", + "line": 883, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "endpoint, path", + "arity": 2, + "function": "static_integrity", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "sigil_p/2", + "line": 367, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, route, __CALLER__, endpoint, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "sigil_p/2", + "line": 368, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, route, __CALLER__, endpoint, router), __CALLER__", + "arity": 2, + "function": "inject_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "sigil_p/2", + "line": 364, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :router", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "sigil_p/2", + "line": 363, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :endpoint", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "sigil_p/2", + "line": 362, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "extra", + "arity": 1, + "function": "validate_sigil_p!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 983, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "test_path, config.statics()", + "arity": 2, + "function": "static_path?", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 982, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path_rewrite", + "arity": 1, + "function": "materialize_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 963, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "config.path_prefixes(), meta", + "arity": 2, + "function": "compile_prefixes", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 960, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Enum.slice(path_rewrite, 0, 1)", + "arity": 1, + "function": "materialize_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 960, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "materialize_path(Enum.slice(path_rewrite, 0, 1)), config.statics()", + "arity": 2, + "function": "static_path?", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "rewrite_path/4", + "line": 956, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "segments, route", + "arity": 2, + "function": "verify_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/3", + "line": 441, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/3", + "line": 442, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", + "arity": 2, + "function": "inject_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/3", + "line": 438, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "extra", + "arity": 1, + "function": "validate_sigil_p!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/3", + "line": 445, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "other", + "arity": 1, + "function": "raise_invalid_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/2", + "line": 476, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", + "arity": 5, + "function": "build_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/2", + "line": 477, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", + "arity": 2, + "function": "inject_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/2", + "line": 473, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "__CALLER__, :router", + "arity": 2, + "function": "attr!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/2", + "line": 472, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "extra", + "arity": 1, + "function": "validate_sigil_p!", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "path/2", + "line": 480, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "other", + "arity": 1, + "function": "raise_invalid_route", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "guarded_unverified_url/3", + "line": 629, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint.url(), path, params", + "arity": 3, + "function": "concat_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "guarded_unverified_url/3", + "line": 628, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "url, path, params", + "arity": 3, + "function": "concat_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "guarded_unverified_url/3", + "line": 634, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint.url(), path, params", + "arity": 3, + "function": "concat_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "guarded_unverified_url/3", + "line": 638, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "URI.to_string(%{uri | path: path}), params", + "arity": 2, + "function": "append_params", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "guarded_unverified_url/3", + "line": 642, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "endpoint.url(), path, params", + "arity": 3, + "function": "concat_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "encode_segment/1", + "line": 753, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "data", + "arity": 1, + "function": "to_param", + "module": "Phoenix.Param" + } + }, + { + "caller": { + "function": "concat_url/3", + "line": 654, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "<>, params", + "arity": 2, + "function": "append_params", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "build_route/5", + "line": 935, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "meta, env", + "arity": 2, + "function": "warn_location", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "build_route/5", + "line": 933, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Phoenix.VerifiedRoutes, %{\n route: nil,\n router: router,\n warn_location: warn_location(meta, env),\n inspected_route: Macro.to_string(sigil_p),\n test_path: test_path\n}", + "arity": 2, + "function": "%", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "build_route/5", + "line": 931, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "route_ast, endpoint_ctx, router, config", + "arity": 4, + "function": "rewrite_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "build_own_forward_path/3", + "line": 1043, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path, local_script", + "arity": 2, + "function": "path_with_script", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "build_conn_forward_path/3", + "line": 1054, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "path, :erlang.++(script_name, local_script)", + "arity": 2, + "function": "path_with_script", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "append_params/2", + "line": 739, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "params", + "arity": 1, + "function": "__encode_query__", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__verify__/1", + "line": 315, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "route.test_path()", + "arity": 1, + "function": "split_test_path", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__verify__/1", + "line": 314, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Phoenix.VerifiedRoutes, %{}", + "arity": 2, + "function": "%", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 230, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__encode_segment__/1", + "line": 747, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "data", + "arity": 1, + "function": "encode_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__encode_segment__/1", + "line": 746, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "encode_segment", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__encode_query__/2", + "line": 897, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "query_str, sort?", + "arity": 2, + "function": "maybe_sort_query", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__encode_query__/2", + "line": 895, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "to_param", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "__encode_query__/2", + "line": 901, + "module": "Phoenix.VerifiedRoutes", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "val", + "arity": 1, + "function": "to_param", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "warn_if_ajax/1", + "line": 1305, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "ajax?", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "view_module/2", + "line": 604, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_safe_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "validate_local_url/1", + "line": 508, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "to", + "arity": 1, + "function": "raise_invalid_url", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "validate_local_url/1", + "line": 518, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "to", + "arity": 1, + "function": "raise_invalid_url", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "validate_jsonp_callback!/1", + "line": 437, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "t", + "arity": 1, + "function": "validate_jsonp_callback!", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "url/1", + "line": 501, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "to", + "arity": 1, + "function": "validate_local_url", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "text/2", + "line": 456, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"text/plain\", String.Chars.to_string(data)", + "arity": 4, + "function": "send_resp", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "send_resp/4", + "line": 1096, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, default_content_type", + "arity": 2, + "function": "ensure_resp_content_type", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "send_download/3", + "line": 1251, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, filename, opts", + "arity": 3, + "function": "prepare_send_download", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "send_download/3", + "line": 1260, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, filename, opts", + "arity": 3, + "function": "prepare_send_download", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "scrub_params/2", + "line": 1338, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "[key: required_key]", + "arity": 1, + "function": "exception", + "module": "Phoenix.MissingParamError" + } + }, + { + "caller": { + "function": "scrub_params/2", + "line": 1335, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Map.get(conn.params(), required_key)", + "arity": 1, + "function": "scrub_param", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "scrub_param/1", + "line": 1351, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "v", + "arity": 1, + "function": "scrub_param", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "scrub_param/1", + "line": 1356, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "", + "arity": 1, + "function": "scrub_param", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "scrub_param/1", + "line": 1360, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "param", + "arity": 1, + "function": "scrub?", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "scrub?/1", + "line": 1363, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "rest", + "arity": 1, + "function": "scrub?", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "root_layout/2", + "line": 849, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_root_layout, format", + "arity": 3, + "function": "get_private_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_with_layouts/4", + "line": 999, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "view, template, format, render_assigns", + "arity": 4, + "function": "template_render_to_iodata", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_with_layouts/4", + "line": 996, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "layout_mod, layout_base, format, root_assigns", + "arity": 4, + "function": "template_render_to_iodata", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_with_layouts/4", + "line": 994, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "view, template, format, render_assigns", + "arity": 4, + "function": "template_render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_with_layouts/4", + "line": 993, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "layout_tpl", + "arity": 1, + "function": "split_template", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_with_layouts/4", + "line": 991, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "root_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_and_send/4", + "line": 984, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, MIME.type(format)", + "arity": 2, + "function": "ensure_resp_content_type", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_and_send/4", + "line": 981, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, view, template, format", + "arity": 4, + "function": "render_with_layouts", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_and_send/4", + "line": 980, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, assigns, template, format", + "arity": 4, + "function": "prepare_assigns", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render_and_send/4", + "line": 979, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "view_module", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/4", + "line": 974, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, view", + "arity": 2, + "function": "put_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/4", + "line": 975, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "put_view(conn, view), template, assigns", + "arity": 3, + "function": "render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 951, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, format, :erlang.atom_to_binary(template), assigns", + "arity": 4, + "function": "render_and_send", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 947, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 957, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 957, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "put_format(conn, format), format, base, assigns", + "arity": 4, + "function": "render_and_send", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 956, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "template", + "arity": 1, + "function": "split_template", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/3", + "line": 966, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, view, template, []", + "arity": 4, + "function": "render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/2", + "line": 873, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, template, []", + "arity": 3, + "function": "render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/2", + "line": 877, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "action_name", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "render/2", + "line": 877, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, action_name(conn), assigns", + "arity": 3, + "function": "render", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "refuse/3", + "line": 1620, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "[\n accepts: accepted,\n message:\n <<\"no supported media type in accept header.\\n\\nExpected one of \"::binary,\n Kernel.inspect(accepted)::binary, \" but got the following formats:\\n\\n * \"::binary,\n Enum.map_join(given, \"\\n \", fn {_, header, exts} ->\n <>\n end)::binary,\n \"\\n\\nTo accept custom formats, register them under the :mime library\\nin your config/config.exs file:\\n\\n config :mime, :types, %{\\n \\\"application/xml\\\" => [\\\"xml\\\"]\\n }\\n\\nAnd then run `mix deps.clean --build mime` to force it to be recompiled.\\n\"::binary>>\n]", + "arity": 1, + "function": "exception", + "module": "Phoenix.NotAcceptableError" + } + }, + { + "caller": { + "function": "redirect/2", + "line": 496, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "Plug.Conn.put_resp_header(conn, \"location\", url), case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 302\n x -> x\nend, \"text/html\", body", + "arity": 4, + "function": "send_resp", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "redirect/2", + "line": 490, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "opts", + "arity": 1, + "function": "url", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_view/2", + "line": 537, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_view, :replace, formats", + "arity": 4, + "function": "put_private_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_secure_browser_headers/2", + "line": 1406, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "put_secure_defaults", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_secure_browser_headers/2", + "line": 1411, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "put_secure_defaults", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_root_layout/2", + "line": 794, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_root_layout, :replace, layout", + "arity": 4, + "function": "put_private_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_view/4", + "line": 553, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, priv_key, kind, formats", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_view/4", + "line": 558, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, priv_key, kind, %{_: value}", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_layout/4", + "line": 702, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, private_key, kind, formats", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_layout/4", + "line": 722, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, private_key, kind, %{_: {mod, layout}}", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_layout/4", + "line": 712, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, private_key, kind, %{_: {mod, layout}}", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_private_layout/4", + "line": 708, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, private_key, kind, %{_: false}", + "arity": 4, + "function": "put_private_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_new_view/2", + "line": 583, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_view, :new, formats", + "arity": 4, + "function": "put_private_view", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_new_layout/2", + "line": 756, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_layout, :new, layout", + "arity": 4, + "function": "put_private_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_layout/2", + "line": 652, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_layout, :replace, layout", + "arity": 4, + "function": "put_private_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_flash/3", + "line": 1706, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "flash_key", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "put_flash/3", + "line": 1706, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :maps.put(flash_key(key), message, flash)", + "arity": 2, + "function": "persist_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "prepare_send_download/3", + "line": 1268, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "warn_if_ajax", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "prepare_send_download/3", + "line": 1267, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "Keyword.get(opts, :disposition, :attachment)", + "arity": 1, + "function": "get_disposition_type", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "prepare_send_download/3", + "line": 1266, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "filename, Keyword.get(opts, :encode, true)", + "arity": 2, + "function": "encode_filename", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "prepare_assigns/4", + "line": 1023, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, assigns, format", + "arity": 3, + "function": "assigns_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "prepare_assigns/4", + "line": 1020, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "assigns", + "arity": 1, + "function": "to_map", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1571, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, t, acc, accepted", + "arity": 4, + "function": "parse_header_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1565, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1567, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, t, [{:erlang.-(q), h, exts} | acc], accepted", + "arity": 4, + "function": "parse_header_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1564, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "exts, accepted", + "arity": 2, + "function": "find_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1562, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "args", + "arity": 1, + "function": "parse_q", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1561, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "type, subtype", + "arity": 2, + "function": "parse_exts", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1579, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, acc, accepted", + "arity": 3, + "function": "refuse", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/4", + "line": 1578, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, capture, accepted", + "arity": 3, + "function": "parse_header_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/3", + "line": 1584, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "parse_header_accept/3", + "line": 1583, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "exts, accepted", + "arity": 2, + "function": "find_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "merge_flash/2", + "line": 1682, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :maps.merge(Map.get(conn.assigns(), :flash, %{}), map)", + "arity": 2, + "function": "persist_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "merge_flash/2", + "line": 1681, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "k", + "arity": 1, + "function": "flash_key", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "layout/2", + "line": 839, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, :phoenix_layout, format", + "arity": 3, + "function": "get_private_layout", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "json/2", + "line": 365, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"application/json\", response", + "arity": 4, + "function": "send_resp", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "json/2", + "line": 364, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "", + "arity": 0, + "function": "json_library", + "module": "Phoenix" + } + }, + { + "caller": { + "function": "html/2", + "line": 469, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"text/html\", data", + "arity": 4, + "function": "send_resp", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "handle_params_accept/3", + "line": 1533, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, format", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "handle_params_accept/3", + "line": 1535, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "remote", + "callee": { + "args": "[\n message:\n <<\"unknown format \"::binary, Kernel.inspect(format)::binary, \", expected one of \"::binary,\n Kernel.inspect(accepted)::binary>>,\n accepts: accepted\n]", + "arity": 1, + "function": "exception", + "module": "Phoenix.NotAcceptableError" + } + }, + { + "caller": { + "function": "handle_header_accept/3", + "line": 1544, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, first", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "handle_header_accept/3", + "line": 1552, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, \"html\"", + "arity": 2, + "function": "put_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "handle_header_accept/3", + "line": 1554, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn, String.split(header, \",\"), [], accepted", + "arity": 4, + "function": "parse_header_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "get_private_layout/3", + "line": 857, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "layout_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "get_private_layout/3", + "line": 853, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_safe_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "get_flash/2", + "line": 1740, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "key", + "arity": 1, + "function": "flash_key", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "get_flash/2", + "line": 1740, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "get_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "find_format/2", + "line": 1614, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "type_range, t", + "arity": 2, + "function": "find_format", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "fetch_flash/2", + "line": 1648, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, case session_flash do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> %{}\n x -> x\nend", + "arity": 2, + "function": "persist_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_url/2", + "line": 1889, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, params", + "arity": 2, + "function": "current_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_url/2", + "line": 1889, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn, current_path(conn, params)", + "arity": 2, + "function": "unverified_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "current_url/1", + "line": 1843, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "current_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_url/1", + "line": 1843, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "conn, current_path(conn)", + "arity": 2, + "function": "unverified_url", + "module": "Phoenix.VerifiedRoutes" + } + }, + { + "caller": { + "function": "current_path/2", + "line": 1823, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "normalized_request_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_path/2", + "line": 1827, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "normalized_request_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_path/1", + "line": 1791, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "normalized_request_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "current_path/1", + "line": 1795, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "normalized_request_path", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "clear_flash/1", + "line": 1768, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, %{}", + "arity": 2, + "function": "persist_flash", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "assigns_layout/3", + "line": 1065, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "layout_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "assigns_layout/3", + "line": 1062, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defp" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "layout_formats", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "assign/2", + "line": 1912, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, fun.(conn.assigns())", + "arity": 2, + "function": "assign", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "allow_jsonp/2", + "line": 409, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn.resp_body(), cb", + "arity": 2, + "function": "jsonp_body", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "allow_jsonp/2", + "line": 406, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn", + "arity": 1, + "function": "json_response?", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "allow_jsonp/2", + "line": 403, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "cb", + "arity": 1, + "function": "validate_jsonp_callback!", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "action_fallback/1", + "line": 315, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defmacro" + }, + "type": "remote", + "callee": { + "args": "plug, __CALLER__", + "arity": 2, + "function": "__action_fallback__", + "module": "Phoenix.Controller.Pipeline" + } + }, + { + "caller": { + "function": "accepts/2", + "line": 1527, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, Plug.Conn.get_req_header(conn, \"accept\"), accepted", + "arity": 3, + "function": "handle_header_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "accepts/2", + "line": 1524, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "local", + "callee": { + "args": "conn, format, accepted", + "arity": 3, + "function": "handle_params_accept", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "__using__/1", + "line": 237, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "defmacro" + }, + "type": "local", + "callee": { + "args": "capture, __CALLER__", + "arity": 2, + "function": "expand_alias", + "module": "Phoenix.Controller" + } + }, + { + "caller": { + "function": "__plugs__/2", + "line": 1920, + "module": "Phoenix.Controller", + "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "kind": "def" + }, + "type": "remote", + "callee": { + "args": "controller_module, \"Controller\"", + "arity": 2, + "function": "unsuffix", + "module": "Phoenix.Naming" + } + } + ], + "function_locations": { + "Phoenix.Logger": { + "keep_values/2:224": { + "line": 224, + "guard": null, + "pattern": "[_ | _] = list, match", + "kind": "defp", + "end_line": 225, + "ast_sha": "68b40be491818866cc341bba414ae2cca5fb86c98d3311b3042b1fb63b0a1195", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "a69c6b0b24b6b7e9cd1351f93449a34b7949d82508f39b4c1e0f1f0fc3dbe2c6", + "start_line": 224, + "name": "keep_values", + "arity": 2 + }, + "status_to_string/1:290": { + "line": 290, + "guard": null, + "pattern": "status", + "kind": "defp", + "end_line": 291, + "ast_sha": "5774021682c3e46b15005ed49240b20bd771ed30ad4d25cb94626e8280dab6b9", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "07a820bad84862e11c23b3dd2f8b6fa7eeac309b9b0eb308aef6392199542337", + "start_line": 290, + "name": "status_to_string", + "arity": 1 + }, + "phoenix_endpoint_stop/4:254": { + "line": 254, + "guard": null, + "pattern": "_, %{duration: duration}, %{conn: conn} = metadata, _", + "kind": "def", + "end_line": 263, + "ast_sha": "6959dc5fc3fa2afb0ccc73bb01eb7ea03cd0e60b2b641a571b07a4bc05aca571", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "e1120def954289075f83dd4125a1a9b5403c888cdb4e8a53bba48d5f34e78e06", + "start_line": 254, + "name": "phoenix_endpoint_stop", + "arity": 4 + }, + "log_level/2:230": { + "line": 230, + "guard": null, + "pattern": "nil, _conn", + "kind": "defp", + "end_line": 230, + "ast_sha": "2a960798449b1c5599f5bbcfbeea9f6d508f53f8fb799474ad84bb42c674c5f5", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "674f87015e517c75bbc19609b0db2864d0f5776c66740c5e751f7eec9f5f9874", + "start_line": 230, + "name": "log_level", + "arity": 2 + }, + "compile_filter/1:164": { + "line": 164, + "guard": null, + "pattern": "{:compiled, _key, _value} = filter", + "kind": "def", + "end_line": 164, + "ast_sha": "84788b066f39448036b69b6dcf8e1082524d0d55e6df457db4a71a8b90cb08f5", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "1bf5081e16d62cad797d358c3aaa0becacf6e99a15c5eea0b288ab506bc00fa9", + "start_line": 164, + "name": "compile_filter", + "arity": 1 + }, + "phoenix_socket_connected/4:343": { + "line": 343, + "guard": null, + "pattern": "_, %{duration: duration}, %{log: level} = meta, _", + "kind": "def", + "end_line": 363, + "ast_sha": "83f6dcfd03a86e2a3e3095a49939a6f251bd4afddbfb1589ebb38e90ee43db79", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "4112c3fed615f316656b55a281c89460714f847cd634a5674eac7fb2101c7561", + "start_line": 343, + "name": "phoenix_socket_connected", + "arity": 4 + }, + "phoenix_error_rendered/4:274": { + "line": 274, + "guard": null, + "pattern": "_, _, %{log: false}, _", + "kind": "def", + "end_line": 274, + "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "0b56753e8b5aa83c3c0ec63375bad252626e3b2114496671bdc6fa32eb66df0b", + "start_line": 274, + "name": "phoenix_error_rendered", + "arity": 4 + }, + "compile_filter/1:167": { + "line": 167, + "guard": null, + "pattern": "params", + "kind": "def", + "end_line": 167, + "ast_sha": "9c689b28d84f333c4cdee7c393f4b3cb01365b6f6bff6fb354fc4731f82f1999", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "a3832c125cbbe711c77bc8de135039d77cabf859b49d385018e75eba65473756", + "start_line": 167, + "name": "compile_filter", + "arity": 1 + }, + "phoenix_error_rendered/4:276": { + "line": 276, + "guard": null, + "pattern": "_, _, %{log: level, status: status, kind: kind, reason: reason}, _", + "kind": "def", + "end_line": 284, + "ast_sha": "849d763d217af8b5b0304d3ee6d308cd473ad9306894411583983dd6a456bde4", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "b5fdd2113d2d5e29a1634adc33374610dd4c6f2966f797e5d4d1f3e915fca2c8", + "start_line": 276, + "name": "phoenix_error_rendered", + "arity": 4 + }, + "discard_values/3:187": { + "line": 187, + "guard": "is_atom(mod)", + "pattern": "%{__struct__: mod} = struct, _key_match, _value_match", + "kind": "defp", + "end_line": 188, + "ast_sha": "0677344ef01535ab3968c984bfe82c08a0e95796a0dd6416b38d1db06486df73", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "eba9bf0a61e1e241a13758df2abf3b0f9cd02ff635e105f303a3f98516adc87d", + "start_line": 187, + "name": "discard_values", + "arity": 3 + }, + "discard_values/3:206": { + "line": 206, + "guard": null, + "pattern": "[_ | _] = list, key_match, value_match", + "kind": "defp", + "end_line": 207, + "ast_sha": "833900488d70e17322687554d54bafd40e3ec55d97b3574da99b2d4400d40cf1", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "e44216b6272c4a56bffa01374bc6284bc792d2502d3cc8bcb8ffb16d50f9f36d", + "start_line": 206, + "name": "discard_values", + "arity": 3 + }, + "phoenix_socket_connected/4:341": { + "line": 341, + "guard": null, + "pattern": "_, _, %{log: false}, _", + "kind": "def", + "end_line": 341, + "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "792adb559a571c69a8ada829c032e479bfa104486dc05e981675727f4b50fa46", + "start_line": 341, + "name": "phoenix_socket_connected", + "arity": 4 + }, + "mfa/3:332": { + "line": 332, + "guard": null, + "pattern": "mod, fun, arity", + "kind": "defp", + "end_line": 333, + "ast_sha": "a9ef9f73fa6db66ecc8e940c2a78f2f65802f6894d97a8cc533d2f55e39ff35e", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "56dbb18a7cacae242822f3616d60a9bed6c75d3a1b4eaa7b9fa71a92cdbc83fa", + "start_line": 332, + "name": "mfa", + "arity": 3 + }, + "log_level/2:231": { + "line": 231, + "guard": "is_atom(level)", + "pattern": "level, _conn", + "kind": "defp", + "end_line": 231, + "ast_sha": "1597b8f80a20229c8406250ebcb8adb2eeb5379ee1f66838df101b68c9faca58", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "1659a71d42ee59447b77b8d1c0eba01883f7136aa00b0a65fd465eac9a231574", + "start_line": 231, + "name": "log_level", + "arity": 2 + }, + "log_level/2:233": { + "line": 233, + "guard": "is_atom(mod) and is_atom(fun) and is_list(args)", + "pattern": "{mod, fun, args}, conn", + "kind": "defp", + "end_line": 234, + "ast_sha": "b59eb55f0ca150c83355622f4371c17e2a5e9feb3c6d144af51c0e0d8a97ae97", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "3c342dbc695a3049bc532f6a105e490ff143a0a5ef014a9cfcce216f517a7eaa", + "start_line": 233, + "name": "log_level", + "arity": 2 + }, + "join_result/1:410": { + "line": 410, + "guard": null, + "pattern": ":ok", + "kind": "defp", + "end_line": 410, + "ast_sha": "32190a99e83d7aaa14bc1a401567f0ab618b8967b812f9f7ffbc5a69f2965bca", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "4b6b5de02d004ba8fac1c98ece1df00a42a4e284b05b88809e35295886f1c207", + "start_line": 410, + "name": "join_result", + "arity": 1 + }, + "phoenix_socket_drain/4:374": { + "line": 374, + "guard": null, + "pattern": "_, %{count: count, total: total, index: index, rounds: rounds}, %{log: level} = meta, _", + "kind": "def", + "end_line": 387, + "ast_sha": "597386b08f3d3b37914a2f6a252163420dc9e49373f379389fadd49f2e665ffd", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "98d4b538ee927fe353a4d5bce273d34c37240510d4c56724d2a585d68651c1c7", + "start_line": 374, + "name": "phoenix_socket_drain", + "arity": 4 + }, + "phoenix_socket_drain/4:372": { + "line": 372, + "guard": null, + "pattern": "_, _, %{log: false}, _", + "kind": "def", + "end_line": 372, + "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "9de507e22fdf8541be2de60af8dcf1d257e879ed4fc1de5607d88f03ec3ecbb9", + "start_line": 372, + "name": "phoenix_socket_drain", + "arity": 4 + }, + "keep_values/2:214": { + "line": 214, + "guard": null, + "pattern": "%{} = map, match", + "kind": "defp", + "end_line": 219, + "ast_sha": "1df18a710793b92d6cd624a98857ce6a574ac5ff20c1ccc2c0d641b0c8780a59", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "8de1ec65730591a9b99378a536764112ed3655d323b7003c60840254d401e920", + "start_line": 214, + "name": "keep_values", + "arity": 2 + }, + "filter_values/1:180": { + "line": 180, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 180, + "ast_sha": "113b8a1a0df2de8e7d95071e8c4bfafac33683f622fabc11b738a15790a7ca8a", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "3325557b23baa8beb25a8426d6244c1fe3f313c02f940a0d5db718c74794186b", + "start_line": 180, + "name": "filter_values", + "arity": 1 + }, + "connect_result/1:369": { + "line": 369, + "guard": null, + "pattern": ":error", + "kind": "defp", + "end_line": 369, + "ast_sha": "296ddb5f8e13460f148fda58e0f433671b85a8f9a891ee9e9a512b1c52154815", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "d68858c75a274f24d2e0851560a6b54c596c129ee94b0a00769b4b9b52ce8a41", + "start_line": 369, + "name": "connect_result", + "arity": 1 + }, + "compile_discard/1:169": { + "line": 169, + "guard": null, + "pattern": "[]", + "kind": "defp", + "end_line": 170, + "ast_sha": "75a838d3a06d00955881f39afbce3399446f1821cced6ae805186ec14b1faa8b", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "27e985578d5dc24f9f75d1459ba34aa039882012ae7fd6e7307677d73034d6df", + "start_line": 169, + "name": "compile_discard", + "arity": 1 + }, + "phoenix_channel_joined/4:395": { + "line": 395, + "guard": null, + "pattern": "_, %{duration: duration}, %{socket: socket} = metadata, _", + "kind": "def", + "end_line": 405, + "ast_sha": "898abde8b42227c8eff66ad18a6ac4495716edd6fdd5d22fb0feb4007f0ee6a1", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "480bc2117d81435e6c8c0952a31e71af83a196bd29d37f80e94e1e6ffe1bdc63", + "start_line": 395, + "name": "phoenix_channel_joined", + "arity": 4 + }, + "channel_log/3:437": { + "line": 437, + "guard": null, + "pattern": "log_option, %{private: private}, fun", + "kind": "defp", + "end_line": 439, + "ast_sha": "8300185ba87a6b8eb86a8661b9dbced760f46ca5adede16941f9e4de1dd6ec71", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "485ebbffe89ae8fa01677cb260d2110700a90719b3296c3f413a1c52c1a05ec0", + "start_line": 437, + "name": "channel_log", + "arity": 3 + }, + "params/1:336": { + "line": 336, + "guard": null, + "pattern": "params", + "kind": "defp", + "end_line": 336, + "ast_sha": "d06ed9b1ba5d56e1ccc4bc90a34c2f42c36e87b78a0a6573c5a3cc96d7f9de16", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "23dd53745bc7215b8a9e8a738c489c1e864ccb61c0190346c56cd46385408747", + "start_line": 336, + "name": "params", + "arity": 1 + }, + "connection_type/1:269": { + "line": 269, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 269, + "ast_sha": "0aecfb8eb38c8094760fe4a064d5f0fe5058e42be3ac412bea9447299090ccc4", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "ebe2fef12328fad951b559fca0b59e444bb7e6d36870f1e8ac3acc619f7b92bc", + "start_line": 269, + "name": "connection_type", + "arity": 1 + }, + "phoenix_router_dispatch_start/4:302": { + "line": 302, + "guard": null, + "pattern": "_, _, metadata, _", + "kind": "def", + "end_line": 327, + "ast_sha": "e9818b047229ba922a642d0885536a2bd89e1590b1182a49aded57b84fd66737", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "1d063e890ecec5738aee7c1c0e19fcd2cfaf1343147fe67da6df834274ca1a55", + "start_line": 302, + "name": "phoenix_router_dispatch_start", + "arity": 4 + }, + "discard_values/3:191": { + "line": 191, + "guard": null, + "pattern": "%{} = map, key_match, value_match", + "kind": "defp", + "end_line": 201, + "ast_sha": "6e0df3beda4b2df3c9a416fe7b5e1dec983401622271b84b180d27c695720b30", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "8df21cce6ca24f7193aa3d543692130fe5926609a16c3c7043cb7d1ded911de9", + "start_line": 191, + "name": "discard_values", + "arity": 3 + }, + "duration/1:153": { + "line": 153, + "guard": null, + "pattern": "duration", + "kind": "def", + "end_line": 159, + "ast_sha": "c9425fc17ed83722ddadc7878ab5c6d1462a37b1d55e72e8869cb0d9ec246c97", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "2e1b3354abfc10967bc41241041a2ec5e1e2f9e634b6d3efb1b4270c3ad2e7dc", + "start_line": 153, + "name": "duration", + "arity": 1 + }, + "discard_values/3:210": { + "line": 210, + "guard": null, + "pattern": "other, _key_match, _value_match", + "kind": "defp", + "end_line": 210, + "ast_sha": "081d77d8b24c56d3d2f1ced7da9afc523a951b357f112d0a4adfbccc53a3a373", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "79c4643f47de518504ec09335482904fc60fbd6be253dbd483a530ccab646dcc", + "start_line": 210, + "name": "discard_values", + "arity": 3 + }, + "keep_values/2:212": { + "line": 212, + "guard": "is_atom(mod)", + "pattern": "%{__struct__: mod}, _match", + "kind": "defp", + "end_line": 212, + "ast_sha": "1120df37236263d86457800b69205fd82b1b2f5b312b39ae90cc9c1438ee0d3f", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "42f9aa5b4342a8cb68561423795d81df2808be81a3b738b50ce0173e6ab86728", + "start_line": 212, + "name": "keep_values", + "arity": 2 + }, + "install/0:135": { + "line": 135, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 148, + "ast_sha": "b4bd05d744e95c12f03bd04bf6f6d11d23769e28bee4bbfbf8d12950d5045738", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "832443bc7c0dd2074c684b123a39dc5bb1dae9485132267684d827bb581d4815", + "start_line": 135, + "name": "install", + "arity": 0 + }, + "error_banner/2:295": { + "line": 295, + "guard": null, + "pattern": "_kind, reason", + "kind": "defp", + "end_line": 295, + "ast_sha": "90cbc8a1793ab10ac819037a8ffbb3cd44ab1a9f5da2a4ef08f0578a15074eb5", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "666b7d1d1ee1fda45a0a91dd4a984e106cfd3b120044c577ba945fa5dba9d6db", + "start_line": 295, + "name": "error_banner", + "arity": 2 + }, + "compile_filter/1:165": { + "line": 165, + "guard": null, + "pattern": "{:discard, params}", + "kind": "def", + "end_line": 165, + "ast_sha": "8748646881577d5cb2a4a71726f6bb3fad96274c66c7fb78076656c63722c72f", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "f10ee0e9ff6c2cb9209e865314f3d1866ec8e25fbd206339229ba7ed19207d32", + "start_line": 165, + "name": "compile_filter", + "arity": 1 + }, + "phoenix_channel_handled_in/4:416": { + "line": 416, + "guard": null, + "pattern": "_, %{duration: duration}, %{socket: socket} = metadata, _", + "kind": "def", + "end_line": 430, + "ast_sha": "6dd1bcc70774f1c9ee445476f1ee8cd8bb3dd37acc84a156e49f95d527954038", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "cd786389ed0ef434fcbdc7d9f7eab180948ae8c9de7c67e38f10f0f439dcbad7", + "start_line": 416, + "name": "phoenix_channel_handled_in", + "arity": 4 + }, + "filter_values/2:180": { + "line": 180, + "guard": null, + "pattern": "values, filter", + "kind": "def", + "end_line": 183, + "ast_sha": "6fb4d6d6a0e0a19ee13f4984e30619e6e544640d8320a7a2ece98ff9c37e9b59", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "4f4aabbad998f4e5e6d2571bfcdced7496cb5b366e8f0f4c9cdf9a03223a939b", + "start_line": 180, + "name": "filter_values", + "arity": 2 + }, + "compile_filter/1:166": { + "line": 166, + "guard": null, + "pattern": "{:keep, params}", + "kind": "def", + "end_line": 166, + "ast_sha": "95c40b9b84a8f7ded2a2e6542d7ca3dca727efae38499f85e3a95bcd43cf7e7c", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "cf16ca2c9ea37d2c60ff56710665733947f51b3c3884e973938aecbf8f903351", + "start_line": 166, + "name": "compile_filter", + "arity": 1 + }, + "channel_log/3:435": { + "line": 435, + "guard": null, + "pattern": "_log_option, %{topic: <<\"phoenix\"::binary, _::binary>>}, _fun", + "kind": "defp", + "end_line": 435, + "ast_sha": "68ff3eb16325ba9ae2cfdd126d75a64ab273b7e2a9964bbee81b7cd1e1d3523f", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "3325b747ea0dc86055ba89811450a6fcdc13fbf892cc63df27889a37832cbd90", + "start_line": 435, + "name": "channel_log", + "arity": 3 + }, + "error_banner/2:294": { + "line": 294, + "guard": null, + "pattern": ":error, %type{}", + "kind": "defp", + "end_line": 294, + "ast_sha": "5bfe4307510d5c948fa935be1f3e5cfc95652af03af68cb7ab9514cb486d0f5b", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "8c24ab8c3102d483e479b4026901aecce6688c70bab202baaf2ef152376bbb13", + "start_line": 294, + "name": "error_banner", + "arity": 2 + }, + "connection_type/1:268": { + "line": 268, + "guard": null, + "pattern": ":set_chunked", + "kind": "defp", + "end_line": 268, + "ast_sha": "878054af58af03c3854cbfbe3aa0dc85c0cb7a76b82c12f1b2cfba0b2f35be71", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "b4ef0ff2a07ab53f0d8f462a841fa656ffc6466868a032dfff4927a08b7b92b8", + "start_line": 268, + "name": "connection_type", + "arity": 1 + }, + "connect_result/1:368": { + "line": 368, + "guard": null, + "pattern": ":ok", + "kind": "defp", + "end_line": 368, + "ast_sha": "0e5eff0e8624c1f68ea12c92568cd77681e338772918e02d1a627e0f05e18570", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "d945b4b2437150b33914cdc628d3a2cbc5072be60071b4777eb1427f9f406632", + "start_line": 368, + "name": "connect_result", + "arity": 1 + }, + "phoenix_router_dispatch_start/4:300": { + "line": 300, + "guard": null, + "pattern": "_, _, %{log: false}, _", + "kind": "def", + "end_line": 300, + "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "f09fe4d48eacc9a1386f6da2d680a74bb7a78a5717f25b4f2037059753b1080e", + "start_line": 300, + "name": "phoenix_router_dispatch_start", + "arity": 4 + }, + "params/1:335": { + "line": 335, + "guard": null, + "pattern": "%Plug.Conn.Unfetched{}", + "kind": "defp", + "end_line": 335, + "ast_sha": "8d2dcbdb89d7028602140b682e49abb2dd544cbcecfcb9e9c5813979fe2d619e", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "3eada96a80fbc62e56e4998ec3e7c61f435136019309aae62dad5c304f15f7d2", + "start_line": 335, + "name": "params", + "arity": 1 + }, + "join_result/1:411": { + "line": 411, + "guard": null, + "pattern": ":error", + "kind": "defp", + "end_line": 411, + "ast_sha": "d8d5946e14902389bdcdb1fe8a1a4b691d346808a904899f1a9f89aa833cc6b9", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "af6eac713e5bb454ecf1dc8c303138b057080a0af99abc66fbe7583e18e4345a", + "start_line": 411, + "name": "join_result", + "arity": 1 + }, + "phoenix_endpoint_start/4:240": { + "line": 240, + "guard": null, + "pattern": "_, _, %{conn: conn} = metadata, _", + "kind": "def", + "end_line": 248, + "ast_sha": "19bd01f8d512d6d7151455aa4a27f55f9175bd5024ee9d0495b48259624a1d83", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "d39f40a75e37f08a984d2d901c916d0ec4f4cc85fb6dd287a14877962f6c29ee", + "start_line": 240, + "name": "phoenix_endpoint_start", + "arity": 4 + }, + "keep_values/2:228": { + "line": 228, + "guard": null, + "pattern": "_other, _match", + "kind": "defp", + "end_line": 228, + "ast_sha": "bbe5b75c8bd9a8ea921f149f4f342e2a6376869f30f76907583963e300c3e128", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "fc92bc9b4a1cbdc9686ea4870370c16e8dc852da193a6f354bfdf4d8dc2965ba", + "start_line": 228, + "name": "keep_values", + "arity": 2 + }, + "compile_discard/1:173": { + "line": 173, + "guard": "is_list(params) or is_binary(params)", + "pattern": "params", + "kind": "defp", + "end_line": 176, + "ast_sha": "d6fa12ede26ea199774251221986268df99c6c90352b057ddab92762f47de4ac", + "source_file": "lib/phoenix/logger.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", + "source_sha": "6431580bb22ce2834eda9d10e26ab2c2fa05f9c0ed4e41ddc9c6c1beaa807239", + "start_line": 173, + "name": "compile_discard", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Notifier": { + "build/1:67": { + "line": 67, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 67, + "ast_sha": "705c901ed15566e179f20f322c253981b6e0e4aaf29ca8353a57f39352f9dcad", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "a1dfdc4222ed3f6c9b3ee9a9c7283f2e0cb95e1635a65368371f1c6469653418", + "start_line": 67, + "name": "build", + "arity": 1 + }, + "build/2:67": { + "line": 67, + "guard": null, + "pattern": "args, help", + "kind": "def", + "end_line": 75, + "ast_sha": "6109f865f775f43a4d52b41565fc2a8ae13036a23097c5051a1fd4d94bbf88d2", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "42bf3fdea4ed469ff991df118801631ebb783cb50a81a3f9b02acca32d61a95d", + "start_line": 67, + "name": "build", + "arity": 2 + }, + "copy_new_files/3:159": { + "line": 159, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", + "kind": "defp", + "end_line": 164, + "ast_sha": "6907288b133e0cd3b352b54524313ac05bbf7f01644d1566b496fcc6e7fb1700", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "afd010c94b1ed0717a64e5d74c7ec68e0fbd170e41b0a5e1e3a16a66f8398c91", + "start_line": 159, + "name": "copy_new_files", + "arity": 3 + }, + "files_to_be_generated/1:167": { + "line": 167, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 170, + "ast_sha": "2949dcdc4f06a5ec7f3ceb39fd976528067b6fce797f924948459617d9058bfa", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "f8995bd9ddf6c92ebcebcddfb25bb652636701a6bfcc49f61601e64bfd2c038a", + "start_line": 167, + "name": "files_to_be_generated", + "arity": 1 + }, + "maybe_print_mailer_installation_instructions/1:182": { + "line": 182, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "def", + "end_line": 212, + "ast_sha": "3120d9941a0a7b10c5e042e6de074cd76a9dd8d591ad0fe25f333b33c17285ba", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "4a2425f2f1537773ed90b370b67cf83c791eabd8ceb53f93f1a0201d78018153", + "start_line": 182, + "name": "maybe_print_mailer_installation_instructions", + "arity": 1 + }, + "parse_opts/1:78": { + "line": 78, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 86, + "ast_sha": "ef5847c6c1e3ab919c512e20f5fa404b3e3df66f0e195d2f8141a06d615f78e3", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "b8123a54ec4f72f3259f14c695c1ff2f31703846c6de7447ad00611f6af54ed9", + "start_line": 78, + "name": "parse_opts", + "arity": 1 + }, + "prompt_for_conflicts/1:174": { + "line": 174, + "guard": null, + "pattern": "context", + "kind": "defp", + "end_line": 177, + "ast_sha": "d01037f8f96adb3720fd48df93ae5059f3d5c64ecff7611c4e157bb8bd3056ce", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "b37e08e41ebe1d8327bba055336126cf15772dc431c6ca55e3ba694a48c5a27a", + "start_line": 174, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "put_context_app/2:89": { + "line": 89, + "guard": null, + "pattern": "opts, nil", + "kind": "defp", + "end_line": 89, + "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", + "start_line": 89, + "name": "put_context_app", + "arity": 2 + }, + "put_context_app/2:91": { + "line": 91, + "guard": null, + "pattern": "opts, string", + "kind": "defp", + "end_line": 92, + "ast_sha": "9e26a188fd13878be719240f94ec8a31edd6a60160fc8b43d78c5d7349d70c5b", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", + "start_line": 91, + "name": "put_context_app", + "arity": 2 + }, + "raise_with_help/1:141": { + "line": 141, + "guard": null, + "pattern": "msg", + "kind": "def", + "end_line": 143, + "ast_sha": "7effe8c17805980aee5a55d576c9d368d357c3d492b34b03b94410691f6d11c0", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "5f7c10c313caa3d8a4aeba153a02ba0759c87d1f7164619a783b2ee39689ec7f", + "start_line": 141, + "name": "raise_with_help", + "arity": 1 + }, + "run/1:36": { + "line": 36, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 63, + "ast_sha": "346f6389231b957f8d780ccb3283d495ab415dd97da84171d579208479c9a0fd", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "9cc09178987452f0d8536931bf17bb76af6847a2dc947a7cebd987993fecf2e8", + "start_line": 36, + "name": "run", + "arity": 1 + }, + "valid_message?/1:135": { + "line": 135, + "guard": null, + "pattern": "message_name", + "kind": "defp", + "end_line": 136, + "ast_sha": "e63e87d583bf89123502fcdbfd284d0e1b7b827f9d570ce74526f0a8a1a56a89", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "949561a13cf25189b80412af5edf7cdc373b8ef60c5e5c9195254754e1d03789", + "start_line": 135, + "name": "valid_message?", + "arity": 1 + }, + "valid_notifier?/1:131": { + "line": 131, + "guard": null, + "pattern": "notifier", + "kind": "defp", + "end_line": 132, + "ast_sha": "90515a02834a5231f175582e29f49b7094db3d44f3de2b7e3021bd9d7fe290f2", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "aa895cd52ae061323c32221503250087cf7a11098204261cd80259d1e57d7a6b", + "start_line": 131, + "name": "valid_notifier?", + "arity": 1 + }, + "validate_args!/2:127": { + "line": 127, + "guard": null, + "pattern": "_, help", + "kind": "defp", + "end_line": 128, + "ast_sha": "873c8953e28d5347834106027feb65963b3938dd49d0bb5855b32b3972468eda", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "8c77bcb01e21510258efb499b659773006a6c1fcd6a2f6c7bef7270820cfbb90", + "start_line": 127, + "name": "validate_args!", + "arity": 2 + }, + "validate_args!/2:95": { + "line": 95, + "guard": null, + "pattern": "[context, notifier | messages] = args, help", + "kind": "defp", + "end_line": 123, + "ast_sha": "72607921fadc8f1cab5686bb2f2a45ad5106948a8be00488e76980b2347bc135", + "source_file": "lib/mix/tasks/phx.gen.notifier.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", + "source_sha": "9aa8f782f7d97e0cf2d4fcfe545531d34b4f089545215a571089f9271466d976", + "start_line": 95, + "name": "validate_args!", + "arity": 2 + } + }, + "Phoenix.Channel": { + "__before_compile__/1:486": { + "line": 486, + "guard": null, + "pattern": "_", + "kind": "defmacro", + "end_line": 486, + "ast_sha": "2681e73c66d15ad41190c1bf9e20ad3330ea04e06714532e046445576f73f289", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "d74a491b61b94096bba5b939e58f61cfb36e6b84727a974fe3b64e1d4ad5f42d", + "start_line": 486, + "name": "__before_compile__", + "arity": 1 + }, + "__on_definition__/6:529": { + "line": 529, + "guard": "is_binary(event)", + "pattern": "env, :def, :handle_out, [event, _payload, _socket], _, _", + "kind": "def", + "end_line": 535, + "ast_sha": "e2ab875d28749e060723bb6bc5df5afc2187bc3441ff7830de74668818e46f94", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "907c38260de927da731df83940254d8b0e97698bb7e0c7a683974b65622e5931", + "start_line": 529, + "name": "__on_definition__", + "arity": 6 + }, + "__on_definition__/6:540": { + "line": 540, + "guard": null, + "pattern": "_env, _kind, _name, _args, _guards, _body", + "kind": "def", + "end_line": 540, + "ast_sha": "a75328168104ff0155e26c3705db2a3929cdc9a95afe6d899d0e2a6f6a0f7c6f", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "a4b9c486df003ba2e748a251f10640de78a9b575f7dc1254629494aab9e8d08c", + "start_line": 540, + "name": "__on_definition__", + "arity": 6 + }, + "__using__/0:450": { + "line": 450, + "guard": null, + "pattern": "", + "kind": "defmacro", + "end_line": 450, + "ast_sha": "a88f188d4c0315e5f1704c916769534fc2199c6f57ee453a573d5b48e6fe4a40", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "fb56688d827619d2515210c956b10943a26eb888dc0f0669239a3d00653a5047", + "start_line": 450, + "name": "__using__", + "arity": 0 + }, + "__using__/1:450": { + "line": 450, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 462, + "ast_sha": "46d94dfb7967ea54d34d6e49a93ceb3c5395080bd4565f42bfdb2de1e88ee8c4", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "06f82690fe3103d9cad1359dd3ecff4e00dd47d771fcd708377247354ac58f8a", + "start_line": 450, + "name": "__using__", + "arity": 1 + }, + "assert_joined!/1:698": { + "line": 698, + "guard": null, + "pattern": "%Phoenix.Socket{joined: true} = socket", + "kind": "defp", + "end_line": 699, + "ast_sha": "9c41d653dfe1a55e90b67bb38dc57a06631a5b121c27d33c90f7afb39f809b46", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "77eb24241c269531a6f0b1aaeee363ba808f128704003e98fb586cc66e578ca3", + "start_line": 698, + "name": "assert_joined!", + "arity": 1 + }, + "assert_joined!/1:702": { + "line": 702, + "guard": null, + "pattern": "%Phoenix.Socket{joined: false}", + "kind": "defp", + "end_line": 703, + "ast_sha": "8e45f082802b69e63114613a69b43b2dd24db250a30b524df7928eeb86a43d62", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "82750266954b20353bdccc689c59f0916199933616ca29e98ef06a019d7ae107", + "start_line": 702, + "name": "assert_joined!", + "arity": 1 + }, + "broadcast!/3:567": { + "line": 567, + "guard": null, + "pattern": "socket, event, message", + "kind": "def", + "end_line": 569, + "ast_sha": "97e5a25a2689cd9c3bf96d966365a61364aad009ba67ccaf115954e2f5b10805", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "42e59da1692c69404c552e4920f5a148ddca2fe52e1a31c2b0636694fcf0b1ac", + "start_line": 567, + "name": "broadcast!", + "arity": 3 + }, + "broadcast/3:559": { + "line": 559, + "guard": null, + "pattern": "socket, event, message", + "kind": "def", + "end_line": 561, + "ast_sha": "e29959bb8b0f10973016f3522ed1f5d9fce5b51bad7e6fe893ff804e1ed99085", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "fe7dfee369a962a331f272f0271cac15bbee96ddedc2fd804f36dec12cd6fd37", + "start_line": 559, + "name": "broadcast", + "arity": 3 + }, + "broadcast_from!/3:598": { + "line": 598, + "guard": null, + "pattern": "socket, event, message", + "kind": "def", + "end_line": 602, + "ast_sha": "9206e2ec20702a4a1d6a89d6112ee1d7c5fb99fb86b673e56815addda7189987", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "f6b7a60fa46cc56a489957631322b5ae2d4d682a1597727ac29ac0c093625f7b", + "start_line": 598, + "name": "broadcast_from!", + "arity": 3 + }, + "broadcast_from/3:588": { + "line": 588, + "guard": null, + "pattern": "socket, event, message", + "kind": "def", + "end_line": 592, + "ast_sha": "bc0c23ecb9d4a7798440d3dfff8697a4b9258db87add59b626d045ef58cc932c", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "ed841c8f640982bc51638cf074c45eea76fc63eedcee419d2d5ef49d652947a6", + "start_line": 588, + "name": "broadcast_from", + "arity": 3 + }, + "intercept/1:522": { + "line": 522, + "guard": null, + "pattern": "events", + "kind": "defmacro", + "end_line": 524, + "ast_sha": "19867477c386c573a513076e323a1f770cb999471e4d3d01aeb8b316104ba3e4", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "c407b3c4019abc6842da4bbee452e0ef4446bad25b227fd73579f8f11175adca", + "start_line": 522, + "name": "intercept", + "arity": 1 + }, + "push/3:628": { + "line": 628, + "guard": null, + "pattern": "socket, event, message", + "kind": "def", + "end_line": 630, + "ast_sha": "7be155e1e3f0a2ba8c461fd544f7e7ee07ae7587ca9fbf1a3b741aa3979350fb", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "daaaa8334577f1ecebc89779ea39342cbd3d67060803bfac5614a03f6b2b2624", + "start_line": 628, + "name": "push", + "arity": 3 + }, + "reply/2:674": { + "line": 674, + "guard": "is_atom(status)", + "pattern": "socket_ref, status", + "kind": "def", + "end_line": 675, + "ast_sha": "d83ea14569b5699211215852f9fa195552640bdd6551a5054a4b8a86ba0203a2", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "8075f715f38dd601ee6e7c27c0d1781f85d763c9916ecafc29d8dfb605a5a605", + "start_line": 674, + "name": "reply", + "arity": 2 + }, + "reply/2:678": { + "line": 678, + "guard": null, + "pattern": "{transport_pid, serializer, topic, ref, join_ref}, {status, payload}", + "kind": "def", + "end_line": 679, + "ast_sha": "1c7b424fa75e7108de8dc3c76bbc7fcaf1fce043261de587ec035743e3e7d67c", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "6130ba990f1d3d2da0f3c1004cdfe8f8dea19df6654d92e83a0c1941fb0c1a44", + "start_line": 678, + "name": "reply", + "arity": 2 + }, + "socket_ref/1:688": { + "line": 688, + "guard": "not (ref == nil)", + "pattern": "%Phoenix.Socket{joined: true, ref: ref} = socket", + "kind": "def", + "end_line": 689, + "ast_sha": "e4af2ad51e49dc122b6c3b3ed63a1812346e8b61f65a1ab9bf501c0a71c2e064", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "59a6dd03576fecc9f0a9e292f797c86d3a4f29ba85d810d7c9fd60edd44d8c54", + "start_line": 688, + "name": "socket_ref", + "arity": 1 + }, + "socket_ref/1:692": { + "line": 692, + "guard": null, + "pattern": "_socket", + "kind": "def", + "end_line": 693, + "ast_sha": "404cca7a186852e83e0880c5e25d0c998707b0ee6af78af0908ea06dc51ce300", + "source_file": "lib/phoenix/channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", + "source_sha": "2d41e437323adf06abdb31411c1b5166e1ef016c035a0ccd701d5a025162f4d6", + "start_line": 692, + "name": "socket_ref", + "arity": 1 + } + }, + "Phoenix.Channel.Server": { + "handle_info/2:356": { + "line": 356, + "guard": null, + "pattern": "{:DOWN, ref, _, _, reason}, ref", + "kind": "def", + "end_line": 357, + "ast_sha": "2864b3427ab1674bb98488f49995cb655c5fe59271b504bdc98724b95162629e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "be0165ddfe906dd8741986ad0375568fa5dc384355711be85a757e54f6f50a0c", + "start_line": 356, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:339": { + "line": 339, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{event: \"phx_drain\"}, %{transport_pid: transport_pid} = socket", + "kind": "def", + "end_line": 344, + "ast_sha": "f3683150a7f605d0a284f6dfb289768c3e29eccebd5c1cd3c1caf1a6aba08b60", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "11d4019583aaa867a7bf54f6e00cac2c6556f57013f299baaf00b41e8e8fee1e", + "start_line": 339, + "name": "handle_info", + "arity": 2 + }, + "socket/1:66": { + "line": 66, + "guard": null, + "pattern": "pid", + "kind": "def", + "end_line": 67, + "ast_sha": "a8a2104af65076c3a4b11e936c86950916bdd0dc93deeb410f4f6dfc266ea6c1", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "c850a02269f1d08b1ca51240add4c61ac189d2b3f1985306f83dce8a5b3dfe75", + "start_line": 66, + "name": "socket", + "arity": 1 + }, + "broadcast!/4:163": { + "line": 163, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, topic, event, payload", + "kind": "def", + "end_line": 171, + "ast_sha": "6f0fa5514d5033d1f47efe1c14b49541a2539dd7cfd46c6f2a6ef00284c9b571", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "daf8827b355f2420ab9df6ec01535a71715e21f7734635f5dcd3c2a9bd0be824", + "start_line": 163, + "name": "broadcast!", + "arity": 4 + }, + "handle_in/1:513": { + "line": 513, + "guard": null, + "pattern": "{:reply, reply, %Phoenix.Socket{} = socket}", + "kind": "defp", + "end_line": 515, + "ast_sha": "a1164ec0ee0282fa8624e94f5eaa1856c356fd4ca76f0494c53e197541a8e02c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "6f7f8236fc9361fc7d00b96366fdb2d03267c71d84fe6dd0cdf625fa155b43cb", + "start_line": 513, + "name": "handle_in", + "arity": 1 + }, + "push/6:248": { + "line": 248, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pid, join_ref, topic, event, payload, serializer", + "kind": "def", + "end_line": 251, + "ast_sha": "2197d80a9ce3c753b1bdba78e6d371c0d46b0a81adc7401e2954378250689109", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "f708e132170922cc628453c15cf81159c50436085f8ad472e64b924ed0130dbb", + "start_line": 248, + "name": "push", + "arity": 6 + }, + "local_broadcast_from/5:231": { + "line": 231, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, from, topic, event, payload", + "kind": "def", + "end_line": 239, + "ast_sha": "014942d44ff4d60b6be655cb9e43d5c51f54c5d372381504a815eaf1a2f45940", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "ddb5e756d20d3bea82e47ba37684cef5045b3b4978d527e9d5731ac0d96a2dec", + "start_line": 231, + "name": "local_broadcast_from", + "arity": 5 + }, + "local_broadcast/4:214": { + "line": 214, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, topic, event, payload", + "kind": "def", + "end_line": 222, + "ast_sha": "65588d77cd2b410fb1bdfdb0624df2cd4aa524c457d189fd8edd9fe0a04a6181", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "68730c2a86acd98506f16d5dd0d1e795b1db3523ce53a72cfe4405e6715fe84b", + "start_line": 214, + "name": "local_broadcast", + "arity": 4 + }, + "reply/6:260": { + "line": 260, + "guard": "is_binary(topic)", + "pattern": "pid, join_ref, ref, topic, {status, payload}, serializer", + "kind": "def", + "end_line": 263, + "ast_sha": "e700ddece593e28bbbb5b4f7779a2b342dbe178c629e4cc351e7b54377a8d5c2", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "e6172d894b8460cb6f9b04eb5ef9c141ba42fc489658bacdbfdc9c32eef1cd51", + "start_line": 260, + "name": "reply", + "arity": 6 + }, + "handle_info/2:365": { + "line": 365, + "guard": null, + "pattern": "msg, %{channel: channel} = socket", + "kind": "def", + "end_line": 372, + "ast_sha": "345868b6fc301f38372aeb21e8616390c76074a90216a7d794511f53ba27cf0e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "f72099ba4bca6fde73dda0b3fc57348556f06257d522d62cbad43229ab948883", + "start_line": 365, + "name": "handle_info", + "arity": 2 + }, + "handle_result/2:462": { + "line": 462, + "guard": null, + "pattern": "{:reply, resp, socket}, :handle_call", + "kind": "defp", + "end_line": 463, + "ast_sha": "2c3c0908d9fe0cd1f5d413ef24cebef3c85e9c58a66fd9f7ae9e82f0bd391729", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "163171b2deb8671472af3d44721d872aad909d3cb44f3dd746691f4df415e342", + "start_line": 462, + "name": "handle_result", + "arity": 2 + }, + "handle_result/2:495": { + "line": 495, + "guard": null, + "pattern": "result, callback", + "kind": "defp", + "end_line": 503, + "ast_sha": "813906960c4a617106fa96223f34b160796b581cd41740c144786bbeaa739e93", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "fa5bbd8da4e276066d5226c2a9208ed91527f736b9855057bbc6de74aa186bd8", + "start_line": 495, + "name": "handle_result", + "arity": 2 + }, + "warn_unexpected_msg/4:559": { + "line": 559, + "guard": null, + "pattern": "fun, arity, msg, channel", + "kind": "defp", + "end_line": 568, + "ast_sha": "1a483d5ef0d15aeebc8725ab9c711a17d223b7b51a7e64439b7c60c28f1093b4", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "dbfef733babb2ac352b35101bba650c8e33793be7a102d7315b7e7518f117ed2", + "start_line": 559, + "name": "warn_unexpected_msg", + "arity": 4 + }, + "handle_result/2:479": { + "line": 479, + "guard": null, + "pattern": "result, :handle_in", + "kind": "defp", + "end_line": 491, + "ast_sha": "f2a2c7a8e31d30441feff82ac5683647653944f2beb14569b28a1dd73eb01643", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "b9a190edb87fcb9583cdbe31478bfdfa8724f22d0aa7ade3b1f926087670f4b7", + "start_line": 479, + "name": "handle_result", + "arity": 2 + }, + "handle_reply/2:538": { + "line": 538, + "guard": "is_atom(status)", + "pattern": "socket, status", + "kind": "defp", + "end_line": 539, + "ast_sha": "8461e06f715bacddb00e5b7b52fe2d37e182566e1ed6b80540d5b713fb3752b8", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "493e5edf87484d7c4af48244cd2c43a78b455443afa5b7308b3c78b3c7f1e909", + "start_line": 538, + "name": "handle_reply", + "arity": 2 + }, + "handle_result/2:466": { + "line": 466, + "guard": "=:=(callback, :handle_call) or =:=(callback, :handle_cast)", + "pattern": "{:noreply, socket}, callback", + "kind": "defp", + "end_line": 468, + "ast_sha": "27d0d44f570815648e7d54013f34b01fa3beb8ee641dccded9d15f56d8cbe72a", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "7529e5cf40a59313bd5ff30f839180b0df082302e948ccb41f468b07069ffc4b", + "start_line": 466, + "name": "handle_result", + "arity": 2 + }, + "dispatch/3:124": { + "line": 124, + "guard": null, + "pattern": "entries, :none, message", + "kind": "def", + "end_line": 126, + "ast_sha": "258bd7ea6db3a50c0ecdd80b7c4297e8ee3e9610a3300a00d9d1b5157830f87e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "0bd1cbaaa940f7f983bacfa47d889fcb45378219ac421d13e046a850fcf54560", + "start_line": 124, + "name": "dispatch", + "arity": 3 + }, + "handle_info/2:327": { + "line": 327, + "guard": null, + "pattern": "%Phoenix.Socket.Message{topic: topic, event: event, payload: payload, ref: ref}, %{topic: topic} = socket", + "kind": "def", + "end_line": 336, + "ast_sha": "81780e05ebae193c23a513a08adfaee07e2b64d8f89ce883e917b32577054365", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "d0cb7503f9d026e5b183d4ac800b0621f42dc8add8dfd37310c0d92b4bf08858", + "start_line": 327, + "name": "handle_info", + "arity": 2 + }, + "handle_cast/2:287": { + "line": 287, + "guard": null, + "pattern": ":close, socket", + "kind": "def", + "end_line": 288, + "ast_sha": "a0d5d5b76106a093249b7ea099cc50cfd365ee1459b6f69097fac68589025fc6", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "0d9cad59ed0be5bc2d3c46d496b90cb5fa7e3e558284845b55f00db95ae4a9f2", + "start_line": 287, + "name": "handle_cast", + "arity": 2 + }, + "handle_call/3:275": { + "line": 275, + "guard": null, + "pattern": ":socket, _from, socket", + "kind": "def", + "end_line": 276, + "ast_sha": "51f9cd965dfcaa9196ce3f40d0fd38baf296d251fe0bace509432f3dab941a0c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "431603d546d3427cf78af67d803d09ee00dcfcbb6fe8d778840ea5884b650408", + "start_line": 275, + "name": "handle_call", + "arity": 3 + }, + "handle_reply/2:542": { + "line": 542, + "guard": null, + "pattern": "_socket, reply", + "kind": "defp", + "end_line": 555, + "ast_sha": "60169b474ab4b72215b56575a95b91997ef6857ce3fb35f73173f4f90ced904c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "2b8317de20222e256962825b319b1dc5baf67d726f80163ebcf7a44fde3e867f", + "start_line": 542, + "name": "handle_reply", + "arity": 2 + }, + "code_change/3:377": { + "line": 377, + "guard": null, + "pattern": "old, %{channel: channel} = socket, extra", + "kind": "def", + "end_line": 381, + "ast_sha": "6bbee65557679547094ccabf38aa619720f562b6418229eb484009b4c2c3e399", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "809027b39e2d8323df4cd5e3b0e3e1d05242a5710ceb5629047bab43f8e7e03a", + "start_line": 377, + "name": "code_change", + "arity": 3 + }, + "handle_cast/2:292": { + "line": 292, + "guard": null, + "pattern": "msg, socket", + "kind": "def", + "end_line": 295, + "ast_sha": "760183522fdf147229dd92f207b45194c6f0e5e27cc696216cb31b9ee0731b6f", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "0bb515c63bc6e1ece8699dd99c444c3188526a354f8e555a53218d0219e462c0", + "start_line": 292, + "name": "handle_cast", + "arity": 2 + }, + "handle_reply/2:527": { + "line": 527, + "guard": "is_atom(status)", + "pattern": "socket, {status, payload}", + "kind": "defp", + "end_line": 534, + "ast_sha": "7e7fdfc39535fd814d74c685864d3dd7d7facf250bd3961a55b23a4de8be59b8", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "c90f75a3cd57da334d1de9fe0e853ff6057670f7b7776aef21982a708fbfed6e", + "start_line": 527, + "name": "handle_reply", + "arity": 2 + }, + "handle_result/2:471": { + "line": 471, + "guard": null, + "pattern": "{:noreply, socket}, _callback", + "kind": "defp", + "end_line": 472, + "ast_sha": "03edfa045df20d8e6db35bd75a6281e3d368a909b0c978ec7692994957ec485f", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "5ed5145658312d82843018e0586aec4a6d94cc75c4cdff98eb6b8b058a268d45", + "start_line": 471, + "name": "handle_result", + "arity": 2 + }, + "dispatch/3:132": { + "line": 132, + "guard": null, + "pattern": "entries, from, message", + "kind": "def", + "end_line": 134, + "ast_sha": "92d59f958c26ef2fd03286b9701819569110a91859c637fe518f67fb7964297e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "8195368492dd2442f82b4b92d725c43c70dfa51505813fc08417bb2188e8d5df", + "start_line": 132, + "name": "dispatch", + "arity": 3 + }, + "join/4:17": { + "line": 17, + "guard": null, + "pattern": "socket, channel, message, opts", + "kind": "def", + "end_line": 56, + "ast_sha": "ecc723b55b1956bfcf794e6e0d18367d1d3052e8b181993c0449b0eeddbdc2ec", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "d2f03cbfe9bad2ac4edd3bc19c04575588364d00b93eeb3ba30464671ad01265", + "start_line": 17, + "name": "join", + "arity": 4 + }, + "broadcast/4:146": { + "line": 146, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, topic, event, payload", + "kind": "def", + "end_line": 154, + "ast_sha": "40cc5edad94182bdffb1c8a7bfe17109675934346f65d651e44938dbafee926c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "5754ab166fd26b55bb52771f91e528a862c7e85c4df49dd2826e79a6d324bca5", + "start_line": 146, + "name": "broadcast", + "arity": 4 + }, + "terminate/2:386": { + "line": 386, + "guard": null, + "pattern": "reason, %{channel: channel} = socket", + "kind": "def", + "end_line": 388, + "ast_sha": "45c61bd47e8bef03718d0d7374093e900e3e85357159e30905feb89b3367f76e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "d10285df9ccf585d63bd97d840a0380568024e8aa13d65deed320437944f58dd", + "start_line": 386, + "name": "terminate", + "arity": 2 + }, + "handle_info/2:323": { + "line": 323, + "guard": null, + "pattern": "%Phoenix.Socket.Message{topic: topic, event: \"phx_leave\", ref: ref}, %{topic: topic} = socket", + "kind": "def", + "end_line": 324, + "ast_sha": "798b269f226e8192301d1a61c44865d80cb847c452340ea503e3904f71681856", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "d1209a07685b705c4fff43d73fa416c7d3a3420381cef57bc2438081aa851af7", + "start_line": 323, + "name": "handle_info", + "arity": 2 + }, + "channel_join/4:400": { + "line": 400, + "guard": null, + "pattern": "channel, topic, auth_payload, socket", + "kind": "defp", + "end_line": 419, + "ast_sha": "55ea2c60c615b00dc2f31234241dc5f631727fdfb3c9eb5ebd53ae61ac7eb720", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "b3b46642ef56a388275141723263006fac2d6ab7ef281984ae56213e098222f7", + "start_line": 400, + "name": "channel_join", + "arity": 4 + }, + "handle_in/1:518": { + "line": 518, + "guard": null, + "pattern": "{:stop, reason, reply, socket}", + "kind": "defp", + "end_line": 520, + "ast_sha": "ca382441c48d21c656a4e6ec56d63bffbe8241872af7af448f6dac54b885a5fd", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "56203d1fae92f66b94f12eaa3925bf803dd25104fc606a23776203c2c583a08e", + "start_line": 518, + "name": "handle_in", + "arity": 1 + }, + "handle_info/2:299": { + "line": 299, + "guard": null, + "pattern": "{Phoenix.Channel, auth_payload, {pid, _} = from, socket}, ref", + "kind": "def", + "end_line": 320, + "ast_sha": "634b3105b588fad6c067e00de33d23f565393644ff98215b8a7a935db3975845", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "f0353694a4fbd00cb5f858570d95c148f367249df2cd277aa7c0041f8468975a", + "start_line": 299, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:360": { + "line": 360, + "guard": null, + "pattern": "{:DOWN, _, _, transport_pid, reason}, %{transport_pid: transport_pid} = socket", + "kind": "def", + "end_line": 362, + "ast_sha": "e20347f264339ccfbddbdf7485780e56c26c511ba078d7739d2612a204473d56", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "a3aee8adce2128a945b3fa0054bbb0d58e74172eeb19d2520640a744be40cd34", + "start_line": 360, + "name": "handle_info", + "arity": 2 + }, + "broadcast_from/5:180": { + "line": 180, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, from, topic, event, payload", + "kind": "def", + "end_line": 188, + "ast_sha": "6ab0b7db49c1933ac5151a2d0d9b1cb1b48096cb870aead285e882243fca887c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "721c806e583f170885a9e4bef17701a5155e4db02e2f461be481015e98e14eb2", + "start_line": 180, + "name": "broadcast_from", + "arity": 5 + }, + "dispatch/3:94": { + "line": 94, + "guard": null, + "pattern": "subscribers, from, %Phoenix.Socket.Broadcast{event: event} = msg", + "kind": "def", + "end_line": 118, + "ast_sha": "f37fb347576027e16ec33628afa48f8172a1e65186a974ee9acf6f7865696af2", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "202bc9e1a8a0f744ea565d4236af2ba5835eb81b84ad093efc8f229d46ba1cc1", + "start_line": 94, + "name": "dispatch", + "arity": 3 + }, + "close/2:76": { + "line": 76, + "guard": null, + "pattern": "pid, timeout", + "kind": "def", + "end_line": 85, + "ast_sha": "5fe5fc74a35e30f292e6dd041039ca09d8bfad9f2766c6ab31712163fe40415e", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "7998e35efe2a9df29edd6db9b9bf88b1eb1f6c92565afe4483f0f175b1309383", + "start_line": 76, + "name": "close", + "arity": 2 + }, + "handle_info/2:347": { + "line": 347, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{topic: topic, event: event, payload: payload}, %Phoenix.Socket{topic: topic} = socket", + "kind": "def", + "end_line": 353, + "ast_sha": "efb9eb36b2e2dc78dd0e4a027de84fca1717ed4f0b1f2d90641acf78d583f5dd", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "fa2de837f4c13a56ab54699469e902aa3dbfceec6e5de8f45cbe0e3e987bf803", + "start_line": 347, + "name": "handle_info", + "arity": 2 + }, + "handle_in/1:523": { + "line": 523, + "guard": null, + "pattern": "other", + "kind": "defp", + "end_line": 524, + "ast_sha": "00414c7f2a4e40fb733da52ddc158e19b2fb28314e47a57dcc6fb98d102eb790", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "6ca51be18d1112b9135be2b758055ec3be67fef450953c1a530db00a1fcf55e5", + "start_line": 523, + "name": "handle_in", + "arity": 1 + }, + "handle_result/2:451": { + "line": 451, + "guard": null, + "pattern": "{:stop, reason, socket}, _callback", + "kind": "defp", + "end_line": 459, + "ast_sha": "0122a2506ca91eca51146a45d6a0eb38c924fc5f028c90fab2f273bb75a0bf7c", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "50e6d144194f0482e54d52e8e01809685c8a533150b4bf8a236b247558bd9d88", + "start_line": 451, + "name": "handle_result", + "arity": 2 + }, + "handle_result/2:475": { + "line": 475, + "guard": null, + "pattern": "{:noreply, socket, timeout_or_hibernate}, _callback", + "kind": "defp", + "end_line": 476, + "ast_sha": "11971865ef9b7bc3076dc9b68daf0d1970c1a3c401fa9acaae12a43ea6aca0d9", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "c437e8fdbdf46e10f827a5dc1c8d6a2585ec44c808a87706809354d5c361ffce", + "start_line": 475, + "name": "handle_result", + "arity": 2 + }, + "init_join/3:424": { + "line": 424, + "guard": null, + "pattern": "socket, channel, topic", + "kind": "defp", + "end_line": 446, + "ast_sha": "796becaaa31e2427b13a0dd29f682f57bcf4a32e29d23b4ce0dfc191ae2d7bb6", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "f09b7bca6bff94176936bbb08c96de02b77a0aff861377927da9aef854547606", + "start_line": 424, + "name": "init_join", + "arity": 3 + }, + "child_spec/1:3": { + "line": 3, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 862, + "ast_sha": "8ed3b2567eb1d06b5e1ddc8a65a6fda3af1902657743e8155a087b9678ec6105", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "9baecdee4a37fc795d674d5fa917e41b41242ec3928f13aeabcfb0f72273fc95", + "start_line": 3, + "name": "child_spec", + "arity": 1 + }, + "terminate/2:394": { + "line": 394, + "guard": null, + "pattern": "_reason, _socket", + "kind": "def", + "end_line": 394, + "ast_sha": "6ea9d1f3cbeeae2b7a87faee305df151f31a28a68533071af2ad45a09374cef3", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "aa96a888a94fc12b44493c46c7cff2b23081f75819653164f5ce33e7680eaaf7", + "start_line": 394, + "name": "terminate", + "arity": 2 + }, + "handle_call/3:280": { + "line": 280, + "guard": null, + "pattern": "msg, from, socket", + "kind": "def", + "end_line": 283, + "ast_sha": "e17317653bc0e2011d3652902c9b171efdaf320a36915673fd988e6f5db1dcf1", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "2df235356d7ae8f71d806ca682a12eb017c9c64bdc8bca5fe36e734d19421aaf", + "start_line": 280, + "name": "handle_call", + "arity": 3 + }, + "send_socket_close/2:507": { + "line": 507, + "guard": null, + "pattern": "%{transport_pid: transport_pid}, reason", + "kind": "defp", + "end_line": 508, + "ast_sha": "f90e65f839ffc6dea598583ef1c983f174b735b828d77c76f3e9ea58a7a773dd", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "42c2725dd46339039e36ef915cbfbe1b5f9083e41ae2051433ff11ee90895337", + "start_line": 507, + "name": "send_socket_close", + "arity": 2 + }, + "init/1:270": { + "line": 270, + "guard": null, + "pattern": "{_endpoint, {pid, _}}", + "kind": "def", + "end_line": 271, + "ast_sha": "73a59c0d656af0d2c6422e1ee6b17ace135c1300274eae83f1442c666892e452", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "5147737227f3adb4a6dcb04481dc9520a7f04407cd4cfa8f8d895fcafe44938c", + "start_line": 270, + "name": "init", + "arity": 1 + }, + "broadcast_from!/5:197": { + "line": 197, + "guard": "is_binary(topic) and is_binary(event)", + "pattern": "pubsub_server, from, topic, event, payload", + "kind": "def", + "end_line": 205, + "ast_sha": "ba85984c3b82d131589c825723bb3f3ed82d705a087d6630ebceeb76b5d97fbb", + "source_file": "lib/phoenix/channel/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", + "source_sha": "0844b18a51d12f499ac8be17a8a55a17b9839fb1565a6dd3270cf64b3b92007f", + "start_line": 197, + "name": "broadcast_from!", + "arity": 5 + } + }, + "Phoenix.Socket.PoolDrainer": { + "child_spec/1:70": { + "line": 70, + "guard": null, + "pattern": "{_endpoint, name, opts} = tuple", + "kind": "def", + "end_line": 77, + "ast_sha": "95914fac4507e7f20bf92f804729f0de26f9bfaf312da9a37d07458e37d6d1d3", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "074b9ef9a9d675c53eb58b8267389327d10ed5425f6f0f5fe2972eb90814ecff", + "start_line": 70, + "name": "child_spec", + "arity": 1 + }, + "code_change/3:68": { + "line": 68, + "guard": null, + "pattern": "_old, state, _extra", + "kind": "def", + "end_line": 940, + "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", + "start_line": 68, + "name": "code_change", + "arity": 3 + }, + "handle_call/3:68": { + "line": 68, + "guard": null, + "pattern": "msg, _from, state", + "kind": "def", + "end_line": 884, + "ast_sha": "d154285ffa31c40a154abcc529ee5f8e6b815c60b9c4c00bbba52fd368dd5b68", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", + "start_line": 68, + "name": "handle_call", + "arity": 3 + }, + "handle_cast/2:68": { + "line": 68, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 929, + "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", + "start_line": 68, + "name": "handle_cast", + "arity": 2 + }, + "handle_info/2:68": { + "line": 68, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 912, + "ast_sha": "f3a7db135487577a5363abbd102490541da1764a380f1536439d2b72f2d79c40", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", + "start_line": 68, + "name": "handle_info", + "arity": 2 + }, + "init/1:86": { + "line": 86, + "guard": null, + "pattern": "{endpoint, name, opts}", + "kind": "def", + "end_line": 91, + "ast_sha": "3b9c622985d1798e8ead8081dad06ee3a3909b4c2a03379340453479b6153edc", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "36a6fd3260e3b430efa08638fbd7347e3c50643d1a95bd2693a43cd6263f6876", + "start_line": 86, + "name": "init", + "arity": 1 + }, + "start_link/1:81": { + "line": 81, + "guard": null, + "pattern": "tuple", + "kind": "def", + "end_line": 82, + "ast_sha": "0a02109cfaaf725e2dc8aaac31c7b9e8cb37868a6073c92ac356c8d46f20afa5", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "46101793a503a33028b0f7fe31e1d38b20c342fa40a48002926eb542315db8b6", + "start_line": 81, + "name": "start_link", + "arity": 1 + }, + "terminate/2:95": { + "line": 95, + "guard": null, + "pattern": "_reason, {endpoint, name, size, interval, log_level}", + "kind": "def", + "end_line": 134, + "ast_sha": "084756897ce61b1727d3b9b2cabcece5c85cea40d436b5529b43a001250ff01f", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "418c8bade3923aa879162a128962380fc5038f4d9ddac474d7f4f03b87f0f7ae", + "start_line": 95, + "name": "terminate", + "arity": 2 + } + }, + "Phoenix.Controller": { + "ajax?/1:1297": { + "line": 1297, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 1300, + "ast_sha": "c2fb29f19e90e578e9a1e8afc5604d24aebeca5a198485c46909a08a3c13f823", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a1fd2bbe1bb6685907b307f9d1ebfd9e44176712565ac438f14ee9e811520eba", + "start_line": 1297, + "name": "ajax?", + "arity": 1 + }, + "render/1:870": { + "line": 870, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 870, + "ast_sha": "b970187717539c65106bb48d7236f5a4f1cda332bb7b38b12cd81123a97b2e87", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "dd860040f378e1fbc8c60b22797bedd0f9f68bce1e17b71513b16800a3012cbd", + "start_line": 870, + "name": "render", + "arity": 1 + }, + "put_private_formats/4:561": { + "line": 561, + "guard": "=:=(kind, :new) or =:=(kind, :replace)", + "pattern": "conn, priv_key, kind, formats", + "kind": "defp", + "end_line": 571, + "ast_sha": "7d129ec2fd2fb21b2a1b7dcc98972f7c9a1ea9e0bf03229ae24205f7af3d7c86", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fbd1dbc700f7c30681b6d3e475967ad8877ae2efce2a0b70a3146fc8164ed059", + "start_line": 561, + "name": "put_private_formats", + "arity": 4 + }, + "put_root_layout/2:792": { + "line": 792, + "guard": null, + "pattern": "%Plug.Conn{state: state} = conn, layout", + "kind": "def", + "end_line": 802, + "ast_sha": "be611d95bf1f1f3a691a2949a91503ff2e25919ab441e9f7c483aef014fcfff7", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2a4b040694706ad18c43f822eb5d01b866af7da88601522967471a3af2f5cedd", + "start_line": 792, + "name": "put_root_layout", + "arity": 2 + }, + "put_router_url/2:1135": { + "line": 1135, + "guard": "is_binary(url)", + "pattern": "conn, url", + "kind": "def", + "end_line": 1136, + "ast_sha": "a190af816e0ce1c8d1aea600683f9a8b79cc9a537ac5982f7ebf8b959e5d842d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "50a9e7507bbec344c41a58b50fe16094429e171d4f1e252d212b0ab07918a30f", + "start_line": 1135, + "name": "put_router_url", + "arity": 2 + }, + "handle_header_accept/3:1543": { + "line": 1543, + "guard": "header == [] or header == [\"*/*\"]", + "pattern": "conn, header, [first | _]", + "kind": "defp", + "end_line": 1544, + "ast_sha": "7e3d33d92abc9606356c3b55c0e2b9548c57b650b140e9f6c508c9fbd5782db4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "976ddbf017bcb8ac4bf62636391942dd4c28fa2d4592cfc524bc242e85ae27a9", + "start_line": 1543, + "name": "handle_header_accept", + "arity": 3 + }, + "put_view/2:536": { + "line": 536, + "guard": "=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)", + "pattern": "%Plug.Conn{state: state} = conn, formats", + "kind": "def", + "end_line": 537, + "ast_sha": "cbcb35d79ba28dc88d34a0b1294f1fa8591747cb9cb826fbace8cb32fe742459", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e5c1a9fd5e79adff20a0dac6a2a1b76ceccaef80b0c6ebea82fb24cdcece35dd", + "start_line": 536, + "name": "put_view", + "arity": 2 + }, + "allow_jsonp/1:392": { + "line": 392, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 392, + "ast_sha": "c5510ef8d68f5585f53e7820a9e5fcd5ceb2658b65d15f29888692bca4555174", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "b284b2563d0d6ada4aa3e62f2ff533517020d4836e0f81555be6e1189fd30752", + "start_line": 392, + "name": "allow_jsonp", + "arity": 1 + }, + "put_flash/3:1701": { + "line": 1701, + "guard": null, + "pattern": "conn, key, message", + "kind": "def", + "end_line": 1706, + "ast_sha": "f32417e9d5a7e9bcbe5557f7c7420c12ee01dad2faa5c7f8fc34f8d966f5ba4d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "854dcfd5df4dc0952e8b6854444aa1c9007b83226b0bf16d29a2ed4649b66a92", + "start_line": 1701, + "name": "put_flash", + "arity": 3 + }, + "__using__/1:234": { + "line": 234, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 242, + "ast_sha": "d9cb19fbe8d224c81533921bead5636aff5a18a154772d0797713a6c61815014", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "1b88dcc851de6d39cda303befaf3069479646f6c92be38085922d977394c126b", + "start_line": 234, + "name": "__using__", + "arity": 1 + }, + "put_secure_browser_headers/2:1405": { + "line": 1405, + "guard": null, + "pattern": "conn, []", + "kind": "def", + "end_line": 1406, + "ast_sha": "331e24e4e7e3f2bef3ef63cc704124309024fdbf4dad21015c206793ced4efda", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a9c79259f61af57db66838a2fea995a65827a731311fa37138fc5a4482796ac7", + "start_line": 1405, + "name": "put_secure_browser_headers", + "arity": 2 + }, + "validate_local_url/1:518": { + "line": 518, + "guard": null, + "pattern": "to", + "kind": "defp", + "end_line": 518, + "ast_sha": "35a9c04127fb190a28ee0a2f5909994b52b78a746be6be9fe008446fc4ebf877", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "385340f1d941c42101fdfa45a100fcc530672f2168185d6483b0b5b5634c7dc9", + "start_line": 518, + "name": "validate_local_url", + "arity": 1 + }, + "text/2:455": { + "line": 455, + "guard": null, + "pattern": "conn, data", + "kind": "def", + "end_line": 456, + "ast_sha": "002d2b26f6c080f0a60c77442c873f21798e964827993d9dbba897b9a9373046", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "d148235ee4f803762c2d81fb04a527dc232dbcd4df0afef827fb31f6b1b7ce68", + "start_line": 455, + "name": "text", + "arity": 2 + }, + "ensure_resp_content_type/2:1100": { + "line": 1100, + "guard": null, + "pattern": "%Plug.Conn{resp_headers: resp_headers} = conn, content_type", + "kind": "defp", + "end_line": 1105, + "ast_sha": "60c4d290261d2c703255b298c1a9c4c53fd7a9881961f295f3af0db138d694d8", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "28d36ad3b44067b6d3b443b8b2bc57b17595c9522b75b60b57b4812169fa92ee", + "start_line": 1100, + "name": "ensure_resp_content_type", + "arity": 2 + }, + "send_download/3:1255": { + "line": 1255, + "guard": null, + "pattern": "conn, {:binary, contents}, opts", + "kind": "def", + "end_line": 1261, + "ast_sha": "780d1925dc565162048293854a3c372f353a6afa3996238fb802f11679d8f0fd", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "46e92378291e04e1e7aa3d4b23ef56be1db317ab1c4c41802e2de3b05df5b40b", + "start_line": 1255, + "name": "send_download", + "arity": 3 + }, + "put_new_layout/2:743": { + "line": 743, + "guard": "(is_tuple(layout) and tuple_size(layout) == 2) or is_list(layout) or layout == false", + "pattern": "%Plug.Conn{state: state} = conn, layout", + "kind": "def", + "end_line": 756, + "ast_sha": "7bfe23c8d97019c2d24b271473d2f955dc378a08ea7bb038b2b94f49f2acc958", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "085c55c6e4ea31a46e57d2e0883b3fa4baf36862272a5c2d69ed90c510f755b1", + "start_line": 743, + "name": "put_new_layout", + "arity": 2 + }, + "get_flash/1:1723": { + "line": 1723, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 1725, + "ast_sha": "7e1585bf8de826c394c785dd34835dc980be75f3b0658ad9c2bfca83b3a598e7", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "8b8e328bc1f714eb0eae8a6aabc374a03c4287d3744e5ccfa86c4797e90d6313", + "start_line": 1723, + "name": "get_flash", + "arity": 1 + }, + "validate_local_url/1:510": { + "line": 510, + "guard": null, + "pattern": "<<\"/\"::binary, _::binary>> = to", + "kind": "defp", + "end_line": 514, + "ast_sha": "9303b9158bf586587017ba6019b19dcf498abbcf07b28bf2458219cad3a4979b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9c4cf5293f8a665c55d9d8dbe080a5b8808c6a30dc6cfbf09831f0cfc2e1819d", + "start_line": 510, + "name": "validate_local_url", + "arity": 1 + }, + "put_private_layout/4:705": { + "line": 705, + "guard": null, + "pattern": "conn, private_key, kind, no_format", + "kind": "defp", + "end_line": 729, + "ast_sha": "6a12556bd9f9161a36ca801ee61a807eab7f73650a7a77ff6db2cf33227b7b19", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9b5ad659fe46e818a53bb1558ad789895d2c8fcbe5f0433abcda59d2bebdc57a", + "start_line": 705, + "name": "put_private_layout", + "arity": 4 + }, + "put_router_url/2:1131": { + "line": 1131, + "guard": null, + "pattern": "conn, %URI{} = uri", + "kind": "def", + "end_line": 1132, + "ast_sha": "2ca9110b64832227f9e15990032d5a3695818a23d4db5d1f17f2aee82513c049", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "d8312a8dbcb335941c30566c92ca9395028d8899d820cc9e0e07bba101629a02", + "start_line": 1131, + "name": "put_router_url", + "arity": 2 + }, + "prepare_assigns/4:1019": { + "line": 1019, + "guard": null, + "pattern": "conn, assigns, template, format", + "kind": "defp", + "end_line": 1034, + "ast_sha": "4f36d9506eabe28e09bb459a9e89d45fca1049f5cfd5a926f805a82615a98b5e", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9190f5748d2cf450e649844d719a1f69ad5cd5f9e49b268f117bd52a6bd1abf3", + "start_line": 1019, + "name": "prepare_assigns", + "arity": 4 + }, + "send_download/2:1243": { + "line": 1243, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 1243, + "ast_sha": "b1a216bf51ba7a321bc7db7a919d4c76223e3f3675135ffaa8ded80f479229ce", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "8f3ae5dd86b69ba3218b03927e3b3f3d22ea5ce57e64d801c44474995c00f3c8", + "start_line": 1243, + "name": "send_download", + "arity": 2 + }, + "send_resp/4:1094": { + "line": 1094, + "guard": null, + "pattern": "conn, default_status, default_content_type, body", + "kind": "defp", + "end_line": 1097, + "ast_sha": "bf0dd88f3528c82d3ce824b53182e9a80bfd8146aa1259344ab2e9e3196392e4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "61a29dba3b3e676850325ce3a9d1c18b9838c3786ed13837a09e5a2654c0b6f1", + "start_line": 1094, + "name": "send_resp", + "arity": 4 + }, + "parse_exts/2:1602": { + "line": 1602, + "guard": null, + "pattern": "type, \"*\"", + "kind": "defp", + "end_line": 1602, + "ast_sha": "967965b94682ab69fc94a42b454418eb7b9707070ed2a20728137be8fe3c58c8", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fe02498fd8c7396e9ef11ede3a008ad8e20d356f304cc8830971df4b7764d8ed", + "start_line": 1602, + "name": "parse_exts", + "arity": 2 + }, + "get_format/1:1174": { + "line": 1174, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 1175, + "ast_sha": "762211201eb2ac1b26110e839ee21d8fca4fc0501ea62f622b03ed031d427ec7", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "befab57236d675b960013203077dcd29419f6d40914f7b0514300d0482b0028c", + "start_line": 1174, + "name": "get_format", + "arity": 1 + }, + "assigns_layout/3:1040": { + "line": 1040, + "guard": null, + "pattern": "conn, _assigns, format", + "kind": "defp", + "end_line": 1070, + "ast_sha": "f5cb6ca222131c3a787118274b5467abad65154f7172b19249d1be63a221050c", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "0c5986028a56b15f71cf295241aa328322a20fcad180b85d6d2aa99bec8992b3", + "start_line": 1040, + "name": "assigns_layout", + "arity": 3 + }, + "put_view/2:540": { + "line": 540, + "guard": null, + "pattern": "%Plug.Conn{} = conn, module", + "kind": "def", + "end_line": 547, + "ast_sha": "52d40ce5fd0ddf5086460ad799ac3146273794581fd5fff82f23dec990fd3f44", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "70d7f8f296056088afb713b36ebc091ca2a279c6c3d9abcd76dcdec0b2d6928f", + "start_line": 540, + "name": "put_view", + "arity": 2 + }, + "url/1:499": { + "line": 499, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 503, + "ast_sha": "8145d86afcc0fe0139a1375e0c5b688ecf5284b5c5cb0a1782d9e6f5e0c4646d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e3ae9e1697f2e7d023a4a9be49572bb92f2f6545cf6cdb37fd43baa378c79a5e", + "start_line": 499, + "name": "url", + "arity": 1 + }, + "view_template/1:347": { + "line": 347, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 348, + "ast_sha": "b8a6d8bba8f38c035747bb2df892adce2d8edce1b61a21804d6219c41fb6179e", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "5416f38872b9d43e68197561c5ecf736d00318dfdd7b4d2282ce8d15b80662f1", + "start_line": 347, + "name": "view_template", + "arity": 1 + }, + "controller_module/1:328": { + "line": 328, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 328, + "ast_sha": "1997b6cfe6a8ae1707e49c74ca90e07118176c745340071a9b2ccb66a3a591cc", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "4b6f14a7018ce41a33d10435a610b6e003b1825c7c2442dbe24f169d5895e852", + "start_line": 328, + "name": "controller_module", + "arity": 1 + }, + "status_message_from_template/1:1754": { + "line": 1754, + "guard": null, + "pattern": "template", + "kind": "def", + "end_line": 1761, + "ast_sha": "e507db1f56229aed49f35d4719c4567640e08c74957c46c26c52318e7df2fc71", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "6d8da504d53dae4f0ca4191cb504fc0ad8e15d3282ccca6682bba4fc1f44b5d4", + "start_line": 1754, + "name": "status_message_from_template", + "arity": 1 + }, + "accepts/2:1521": { + "line": 1521, + "guard": null, + "pattern": "conn, [_ | _] = accepted", + "kind": "def", + "end_line": 1527, + "ast_sha": "ce65a68b3815c663c41c1b3591bdb7fc7f77d7f133b9148480902b384ce1d581", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "469b3dd19d6def8e6e7edf0644b5f7f518d57f936898cada4765038f443d4976", + "start_line": 1521, + "name": "accepts", + "arity": 2 + }, + "scrub_param/1:1345": { + "line": 1345, + "guard": "is_atom(mod)", + "pattern": "%{__struct__: mod} = struct", + "kind": "defp", + "end_line": 1346, + "ast_sha": "3c96f428805c576ced518e7c69493c9027665fd62e3be5fa00015221f9b3d03e", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "cc55bdd6d83af45f1386ede861553b01a7a1f04efa30cb183091c96aef67b75c", + "start_line": 1345, + "name": "scrub_param", + "arity": 1 + }, + "send_download/3:1245": { + "line": 1245, + "guard": null, + "pattern": "conn, {:file, path}, opts", + "kind": "def", + "end_line": 1252, + "ast_sha": "ff086f7536843e6578747380a255434493f030a65ba3482f8a57c67b69e45106", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e4e5f5f8a94040a3b2ed63282a86de3c7b86d103ebcf6deccb7108966d83d434", + "start_line": 1245, + "name": "send_download", + "arity": 3 + }, + "parse_header_accept/4:1558": { + "line": 1558, + "guard": null, + "pattern": "conn, [h | t], acc, accepted", + "kind": "defp", + "end_line": 1571, + "ast_sha": "af5a604ca310c09ee08116949e0d3ee1267b6160bbee8c6c7751a6fe034b7e37", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "4725f18268e80c50c5a9f05a200f749d033ff6d79b0e3701321910d7314530f6", + "start_line": 1558, + "name": "parse_header_accept", + "arity": 4 + }, + "view_module/2:603": { + "line": 603, + "guard": null, + "pattern": "conn, format", + "kind": "def", + "end_line": 616, + "ast_sha": "feeed6ad7c48f85a388df04ae4a1700a3588528d94e2b49dc97dae68347c4075", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fcafec71384bb5901a55529d27e20b9b6de8e6a6a74fd2e7fc2321c95cdd73d0", + "start_line": 603, + "name": "view_module", + "arity": 2 + }, + "get_disposition_type/1:1290": { + "line": 1290, + "guard": null, + "pattern": "other", + "kind": "defp", + "end_line": 1294, + "ast_sha": "465b4e3af0fb0a6eed1b1c8dda8a89124643f5cb093a81c29630e8e0477119a4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e2fb12616796915846c1e9a38832c5e8493995f45de69007bc501f6e51197b89", + "start_line": 1290, + "name": "get_disposition_type", + "arity": 1 + }, + "scrub?/1:1363": { + "line": 1363, + "guard": null, + "pattern": "<<\" \"::binary, rest::binary>>", + "kind": "defp", + "end_line": 1363, + "ast_sha": "44187f34f742ddb4b7e76b404990334c19775f6063d5f2a913f4f615ba82eb2f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "77fcdbea1564eb9596cb6e55beddbcb33e1490bc5590093c62c6046188f3f7be", + "start_line": 1363, + "name": "scrub?", + "arity": 1 + }, + "json_response?/1:417": { + "line": 417, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 421, + "ast_sha": "262906d4d62539aeadcc1a5cf47fe1500d10c4d2c8ec8bc4a8c1ad84c47850e5", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "304b962e4ed09b1e663ff67115e26461112159f9911939754dba3a7e6e5d49cf", + "start_line": 417, + "name": "json_response?", + "arity": 1 + }, + "render/2:872": { + "line": 872, + "guard": "is_binary(template) or is_atom(template)", + "pattern": "conn, template", + "kind": "def", + "end_line": 873, + "ast_sha": "ccb5744a99ce3e0a6039ea84779249b9f768c2d15efe6b1ff0027e95271ce755", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "490fbad4c87f9c40a033735cf15cf7cf45831c92f0eb2101a48a1b86ca458edf", + "start_line": 872, + "name": "render", + "arity": 2 + }, + "prepare_send_download/3:1264": { + "line": 1264, + "guard": null, + "pattern": "conn, filename, opts", + "kind": "defp", + "end_line": 1281, + "ast_sha": "f3998c36e0937e176f16d48482ca48a0bc47e16ccc5ed323e24f6913243e674a", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "0521ce242b156847430264d6d3af6dd42239faf9d655f1f7800feecc36f0a3ce", + "start_line": 1264, + "name": "prepare_send_download", + "arity": 3 + }, + "put_static_url/2:1150": { + "line": 1150, + "guard": "is_binary(url)", + "pattern": "conn, url", + "kind": "def", + "end_line": 1151, + "ast_sha": "94782649cf09a7ceafa65dabc76e5bf57ff174b7451cad7a9432870378eea93c", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "7bdc8491453602d751a72f2686841d66102754caa75d9fc51bd4280df8b2e654", + "start_line": 1150, + "name": "put_static_url", + "arity": 2 + }, + "validate_jsonp_callback!/1:439": { + "line": 439, + "guard": null, + "pattern": "<<>>", + "kind": "defp", + "end_line": 439, + "ast_sha": "6b2887dfe346231ae6007d22fc02dcec5aec7b6b4cc023ada14fbf5d49bcec4f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "83b18aa6913df34d6699b18b594b7e7f58d21bc94040270cd5cc1260e9538d71", + "start_line": 439, + "name": "validate_jsonp_callback!", + "arity": 1 + }, + "scrub_params/2:1334": { + "line": 1334, + "guard": "is_binary(required_key)", + "pattern": "%Plug.Conn{} = conn, required_key", + "kind": "def", + "end_line": 1342, + "ast_sha": "43d683234d8780db6fdbc63df1fccddfdc45e63c4a099ee7aa771393525d6eb4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "89cfbe4b8aa66f9ecc1adc040f0eb1c2b8ea0261f607e44cf6b2410d4e3e7ff2", + "start_line": 1334, + "name": "scrub_params", + "arity": 2 + }, + "put_format/2:1164": { + "line": 1164, + "guard": null, + "pattern": "conn, format", + "kind": "def", + "end_line": 1164, + "ast_sha": "d1a635e6cac22bb92524d47f32121ccd5587bc0be0d3628d41d3800a3aa69ae0", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2d144a7f21246f21bf02a7440e43702544810a4f314c28ae31501109efac2857", + "start_line": 1164, + "name": "put_format", + "arity": 2 + }, + "scrub?/1:1365": { + "line": 1365, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 1365, + "ast_sha": "2763a3b03612efd2e097027cccbeeda1985f09b99f38f4ccb9b7201c73c48ea6", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "df23cb95ef9df066e43cad816d28eb69049316cb7df7b8758c85f5f2c093fd8e", + "start_line": 1365, + "name": "scrub?", + "arity": 1 + }, + "put_private_view/4:551": { + "line": 551, + "guard": "is_list(formats)", + "pattern": "conn, priv_key, kind, formats", + "kind": "defp", + "end_line": 553, + "ast_sha": "b9dd392ad21e1ec4cbe739f9498e7908fccd9c4d2005df2e192f2577d88a66a0", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "998156844dd31351432d6777f790d21837cb8cf3dfc06913c6c0c3236d3ae989", + "start_line": 551, + "name": "put_private_view", + "arity": 4 + }, + "get_disposition_type/1:1287": { + "line": 1287, + "guard": null, + "pattern": ":attachment", + "kind": "defp", + "end_line": 1287, + "ast_sha": "3cbfebabfeced6fd6bcea76a938231a742f32fe800e5c989998ee41c4e6e5bd4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "16e4cb2b2ee73980450b93787e5f48841f0e8ea77c3470cee9bde0304f7f3f7e", + "start_line": 1287, + "name": "get_disposition_type", + "arity": 1 + }, + "render_with_layouts/4:988": { + "line": 988, + "guard": null, + "pattern": "conn, view, template, format", + "kind": "defp", + "end_line": 999, + "ast_sha": "9e85024310c0948d12be965eb0247a35cf546a2a775a2789af9d4236615b198f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2e4ecd22dcf4b26f95cb05bcf1f4165a5bb1cfd9061f4ca60229a6824899d3d5", + "start_line": 988, + "name": "render_with_layouts", + "arity": 4 + }, + "action_fallback/1:314": { + "line": 314, + "guard": null, + "pattern": "plug", + "kind": "defmacro", + "end_line": 315, + "ast_sha": "a4a0b60eb8e61c25c096199bcc3b2cc06e04cad25698668ec76a71d291cd2346", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "619a8d8ab7f599c2134a21099ae7e6c065e0b7dc9d6b4eccae72736cfd776c85", + "start_line": 314, + "name": "action_fallback", + "arity": 1 + }, + "find_format/2:1606": { + "line": 1606, + "guard": "is_list(exts)", + "pattern": "exts, accepted", + "kind": "defp", + "end_line": 1606, + "ast_sha": "250f6e7edbf9be94262eaf262241716c96de9cf74fdbd6e416372aa37b0ee2aa", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "3eb9018739ffb8f091e84e5929b6f71cb2547b63efefdac065a99f4ca0d0e458", + "start_line": 1606, + "name": "find_format", + "arity": 2 + }, + "put_layout/2:650": { + "line": 650, + "guard": null, + "pattern": "%Plug.Conn{state: state} = conn, layout", + "kind": "def", + "end_line": 660, + "ast_sha": "628f2daca7c9fe30a6e11e0d8ce9ff4c2eef78f0e7c7e2bc402d03f67b1b3c7d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e191c8c2309560b2c9b073f1cf010105de947cbb0395130dd1c199cc33b4f8a0", + "start_line": 650, + "name": "put_layout", + "arity": 2 + }, + "template_render/4:1003": { + "line": 1003, + "guard": null, + "pattern": "view, template, format, assigns", + "kind": "defp", + "end_line": 1007, + "ast_sha": "5180602446f288e4ffece0cde935ed11a85e12c5c5327026e6688de158a8f1a3", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "597ebb366c031e88b6ee8255cba67c4d93936127d25462d7c16bc2813be0d793", + "start_line": 1003, + "name": "template_render", + "arity": 4 + }, + "to_map/1:1075": { + "line": 1075, + "guard": "is_map(assigns)", + "pattern": "assigns", + "kind": "defp", + "end_line": 1075, + "ast_sha": "9057b63c0142b7ef59737478055b3b9a77fb535a6cf8975a9c2950766327b31b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "83a271ead9f120c9b640f5212110fd5f0fe109d647f494741e8b668f4937461e", + "start_line": 1075, + "name": "to_map", + "arity": 1 + }, + "validate_jsonp_callback!/1:441": { + "line": 441, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 442, + "ast_sha": "b200b6b6aead937fc213b7c47ef4a7c3111d2956a08c76ab5a5f7cbd95749cc2", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "bb1c5d3cc376330c404f46f4bb6cc85e72eece059b915e76c4c5bb2719451a88", + "start_line": 441, + "name": "validate_jsonp_callback!", + "arity": 1 + }, + "fetch_flash/1:1643": { + "line": 1643, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 1643, + "ast_sha": "62a94c8c1075116df5f0f6cd7f81df4071c7a68a286eeeae1b5f59584cf97424", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "ae32afd06e04afa41f9ef6f35112bb5538f2f16f100b231deb37458f24a9b90d", + "start_line": 1643, + "name": "fetch_flash", + "arity": 1 + }, + "render/2:876": { + "line": 876, + "guard": null, + "pattern": "conn, assigns", + "kind": "def", + "end_line": 877, + "ast_sha": "75bffeac579a30d8f5eabb8de7cc04593c3352a1ab0a33a0d6e65127e2add4e4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "acfa45daec8ad7bd6a148997f4370b0dac95f52587733c031eea33c7a5a9dbba", + "start_line": 876, + "name": "render", + "arity": 2 + }, + "merge_flash/2:1680": { + "line": 1680, + "guard": null, + "pattern": "conn, enumerable", + "kind": "def", + "end_line": 1682, + "ast_sha": "0075f7a2db9572637c813c5b61866fbc741491471b2b70e239c75318b6b38050", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fd37cf59e3c9455fac8e7190c260b6cf1e66792f81fd5bd85065823ba624f3d7", + "start_line": 1680, + "name": "merge_flash", + "arity": 2 + }, + "protect_from_forgery/2:1376": { + "line": 1376, + "guard": null, + "pattern": "conn, opts", + "kind": "def", + "end_line": 1377, + "ast_sha": "12550dd67d55640891eeeb9994131d22304718481be8a23a9dee285bdd1dbba8", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "957508a679449c3569633812bc43de0281fb6c0fb0b585eb19650a8c7f99c410", + "start_line": 1376, + "name": "protect_from_forgery", + "arity": 2 + }, + "get_safe_format/1:1178": { + "line": 1178, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 1182, + "ast_sha": "cac3e57f51be5ae07219b93f639f10fc2f9ced8f9bc22cc5c99232af286f4bd7", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "41ade671c952dd9efa12257750486117aeb42038759fbdef4dc111040d1ff5d4", + "start_line": 1178, + "name": "get_safe_format", + "arity": 1 + }, + "view_module/1:603": { + "line": 603, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 603, + "ast_sha": "64fa8b371bb0c7032a1c0e06d7c4dd8d809ef74df93bd546609010ef9692339b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2517fc2ca6ef26c2535d1e4fc51f42c00b26a34c2f90a29d36cef36b309abc0e", + "start_line": 603, + "name": "view_module", + "arity": 1 + }, + "html/2:468": { + "line": 468, + "guard": null, + "pattern": "conn, data", + "kind": "def", + "end_line": 469, + "ast_sha": "ad1a23a4a8294ad198dd56563c69c4bd832107c756cafd93a3fd13b810a8b00f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2d474e3edb5b58ee5832fad34a00bbd143eb9b23ccac5640d5b75ac2403c724b", + "start_line": 468, + "name": "html", + "arity": 2 + }, + "find_format/2:1607": { + "line": 1607, + "guard": null, + "pattern": "_type_range, []", + "kind": "defp", + "end_line": 1607, + "ast_sha": "53add9fe63364ca116c0eefec419000c6e08a35c18699990fce50c7f2555ee1d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "cbc0a81a4aaa69ca7a41255bdc4af9f1d943dd3a6f819d5c6946fad3f5dd27f3", + "start_line": 1607, + "name": "find_format", + "arity": 2 + }, + "handle_header_accept/3:1550": { + "line": 1550, + "guard": null, + "pattern": "conn, [header | _], accepted", + "kind": "defp", + "end_line": 1554, + "ast_sha": "9c4f9decfb17ddd26eb8a4aa43f0aa7057de4bcf1fad010ab7ba7fe178f8429a", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "45f8afac1b548d2f1d22bd39f56fe97c2f6be4f3cab54d1ddd53699711415686", + "start_line": 1550, + "name": "handle_header_accept", + "arity": 3 + }, + "current_path/2:1822": { + "line": 1822, + "guard": "params == %{}", + "pattern": "%Plug.Conn{} = conn, params", + "kind": "def", + "end_line": 1823, + "ast_sha": "21a4bb88ffd66e7e0ffc57aacb60f7211fcd6071bbd7f3563339d4b7a072f3ed", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e2892e6002e27cc61e09eea41a8fac7b5350c5c50979a2bb706a2ca87740b41d", + "start_line": 1822, + "name": "current_path", + "arity": 2 + }, + "redirect/2:489": { + "line": 489, + "guard": "is_list(opts)", + "pattern": "conn, opts", + "kind": "def", + "end_line": 496, + "ast_sha": "874a70e2e6549ac003fb2a257f98ad7ca3fbe7eb051c101fa573f94a746e28cf", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "854f06197e97e431abd7fd92115489b8928d59cf388a3386d8418821ea45c525", + "start_line": 489, + "name": "redirect", + "arity": 2 + }, + "get_disposition_type/1:1288": { + "line": 1288, + "guard": null, + "pattern": ":inline", + "kind": "defp", + "end_line": 1288, + "ast_sha": "d3aeae7d7632d52596e863cf9c760dca4e95f46b99449b82d5d5c4a1095503a5", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a8fc634bf398d106c2a5161b6fe1cd1c42c0ffe999851ba6965a3d8926c73480", + "start_line": 1288, + "name": "get_disposition_type", + "arity": 1 + }, + "to_map/1:1076": { + "line": 1076, + "guard": "is_list(assigns)", + "pattern": "assigns", + "kind": "defp", + "end_line": 1076, + "ast_sha": "74bd6e6e2b2ab2e70f8ce68e65c51ca532e96ec9019619feb7e76d47c65500a8", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9afa93dc3d37d31e7a1ef9f3efb9e708c0db448e1368cd7cae5d9e83600b07fc", + "start_line": 1076, + "name": "to_map", + "arity": 1 + }, + "put_new_view/2:586": { + "line": 586, + "guard": null, + "pattern": "%Plug.Conn{} = conn, module", + "kind": "def", + "end_line": 593, + "ast_sha": "ccc653c5507a4305e46f4ac99173601070dd32007f1362388d2212e53b3f622e", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fa14a991d268c5b4b717d0b31f135443bc5457c6ed0f6f7c036a34ab92af1a51", + "start_line": 586, + "name": "put_new_view", + "arity": 2 + }, + "find_format/2:1609": { + "line": 1609, + "guard": null, + "pattern": "type_range, [h | t]", + "kind": "defp", + "end_line": 1614, + "ast_sha": "01a0f14574078e94a64a30725e43950573ea7a181dd48248141b6fe315531b9f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "aefb1cb0ea0ce3d215711d2e2d2dbc3302f3be7d240b3306b75156237a1e7031", + "start_line": 1609, + "name": "find_format", + "arity": 2 + }, + "flash_key/1:1771": { + "line": 1771, + "guard": "is_binary(binary)", + "pattern": "binary", + "kind": "defp", + "end_line": 1771, + "ast_sha": "db055723bd00d07de072c4bdfb3d4b5dbbc2b119ff5e00d3057446c081ad56fe", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "1466e47c43ddeec358f7fb2a2c1f4b79ce1fc6ceddccc1cac12cfc5b66bcf5a4", + "start_line": 1771, + "name": "flash_key", + "arity": 1 + }, + "put_layout_formats/2:810": { + "line": 810, + "guard": "(=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)) and\n is_list(formats)", + "pattern": "%Plug.Conn{state: state} = conn, formats", + "kind": "def", + "end_line": 812, + "ast_sha": "9dc51f64ef8b14d9bfff2346af0512c74d81a97201be758cd5a21e427cdcf4f6", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "16a6890b4cc432c71daed1730d4a77180c2db49a0a0c7d010036b628fc290297", + "start_line": 810, + "name": "put_layout_formats", + "arity": 2 + }, + "current_path/1:1794": { + "line": 1794, + "guard": null, + "pattern": "%Plug.Conn{query_string: query_string} = conn", + "kind": "def", + "end_line": 1795, + "ast_sha": "b9c9befc869019ed0bb55e65223a9b1696a33746dd1e59cc7ea18ce1d8c5e365", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fa6f683447039dbe4cf8804e528a72e229b4cbb5973ef1d90c3698d44374ce5c", + "start_line": 1794, + "name": "current_path", + "arity": 1 + }, + "put_layout_formats/2:815": { + "line": 815, + "guard": null, + "pattern": "%Plug.Conn{} = conn, _formats", + "kind": "def", + "end_line": 821, + "ast_sha": "ca22641220017cc6897de57eab84598f8ab0f937196945ee6dcaecafd33962c9", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9020dd293866ec1cf579cdaa7b5ffd4ecec085100f547e83287fd10de6aa6601", + "start_line": 815, + "name": "put_layout_formats", + "arity": 2 + }, + "template_render_to_iodata/4:1011": { + "line": 1011, + "guard": null, + "pattern": "view, template, format, assigns", + "kind": "defp", + "end_line": 1015, + "ast_sha": "c3a094e44ee4119df485ca99035d34cc92f5797ff7b4cc5b6d3bc78a56120486", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "62d5afb628a7ce6d6be67f1bb27977f3c5b6dcad8cf871574a2ef3b0279c7b56", + "start_line": 1011, + "name": "template_render_to_iodata", + "arity": 4 + }, + "refuse/3:1619": { + "line": 1619, + "guard": null, + "pattern": "_conn, given, accepted", + "kind": "defp", + "end_line": 1627, + "ast_sha": "4b077b6024042e453de82bacd80d1f0dfbba347491fb2d1db8c8ff12a5f19f51", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "3fdd04294a7784fa88b43ee5f398dfef6e86daf181977162ec1c3220669fec3e", + "start_line": 1619, + "name": "refuse", + "arity": 3 + }, + "assign/2:1911": { + "line": 1911, + "guard": "is_function(fun, 1)", + "pattern": "conn, fun", + "kind": "def", + "end_line": 1912, + "ast_sha": "0450746cc002d1f5f1925d618bbdcf42d065e2542525b0e482d04c304eca45cd", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "d22b37b3cfa7c96647070dd962f048e007266db2126298e4e0c7bc81e9845612", + "start_line": 1911, + "name": "assign", + "arity": 2 + }, + "find_format/2:1605": { + "line": 1605, + "guard": null, + "pattern": "\"*/*\", accepted", + "kind": "defp", + "end_line": 1605, + "ast_sha": "64a41935f028d3137f6185e233a9cd9ba92fe5e1d4f2a763b45c123e77d89ecf", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "20df83462bf3808f1b60364d3eeb26ead339760856a01d847e435281c31c1c8a", + "start_line": 1605, + "name": "find_format", + "arity": 2 + }, + "render/4:971": { + "line": 971, + "guard": "is_atom(view) and (is_binary(template) or is_atom(template))", + "pattern": "conn, view, template, assigns", + "kind": "def", + "end_line": 975, + "ast_sha": "9fc42543c7a285b210ce654ce4363fd4bd9dbedfd39b80b8534e5ff8c5976e59", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "5ad8b8b264791462043c229a6307fadb31fe27b8923c0f9f38f97fa19960e5eb", + "start_line": 971, + "name": "render", + "arity": 4 + }, + "get_flash/2:1739": { + "line": 1739, + "guard": null, + "pattern": "conn, key", + "kind": "def", + "end_line": 1740, + "ast_sha": "ba6a2680f2cc5935c99205a3884f2a681889f3d0392221c5168b1bb3e4b2e9f9", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9ae81ea98ff9d6d1d3952f5904fc889f6674601bd9016cd86f2c1c65bd6de1ad", + "start_line": 1739, + "name": "get_flash", + "arity": 2 + }, + "root_layout/2:848": { + "line": 848, + "guard": null, + "pattern": "conn, format", + "kind": "def", + "end_line": 849, + "ast_sha": "043cc56089c458a0a55d08c6eafae7aed7125c013a0aac0c8fe562391d3e9a9b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "7d7775d22db4f6b9673391ea77a9e23930a029d05062a4bbdc3e560391bdddf1", + "start_line": 848, + "name": "root_layout", + "arity": 2 + }, + "parse_header_accept/3:1582": { + "line": 1582, + "guard": null, + "pattern": "conn, {_, _, exts}, accepted", + "kind": "defp", + "end_line": 1584, + "ast_sha": "2e4533834fa868cee0038ca71de2d9594deb0d90839665c3259b559637cabc81", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "62dca9b44490bc9f88579a140664df7906b881b26c356b561996a327d58b0058", + "start_line": 1582, + "name": "parse_header_accept", + "arity": 3 + }, + "raise_invalid_url/1:521": { + "line": 521, + "guard": null, + "pattern": "url", + "kind": "defp", + "end_line": 522, + "ast_sha": "1ff503875f8d3ed00201b798240b73006c1e34235c5c2271a56d3bc969ef096c", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "df1aba13b8337c1d617079ecfd70e140e7370adbabe3786217e9edc77cc8d94e", + "start_line": 521, + "name": "raise_invalid_url", + "arity": 1 + }, + "assigns_layout/3:1038": { + "line": 1038, + "guard": null, + "pattern": "_conn, %{layout: layout}, _format", + "kind": "defp", + "end_line": 1038, + "ast_sha": "54fc6a4fed446ab5cebdf09288c66512292c9a2ca1f0184be1bc6bfb7ed70c7d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "0e36f1177e07650cbbbcd17ff5c18f613f72ec1277fd8e30d6465a11756a7786", + "start_line": 1038, + "name": "assigns_layout", + "arity": 3 + }, + "current_url/2:1888": { + "line": 1888, + "guard": null, + "pattern": "%Plug.Conn{} = conn, %{} = params", + "kind": "def", + "end_line": 1889, + "ast_sha": "774caa3821cc1eebaf9d6f68e0b9703f70ee62a8662b0644d76f90d2cab6cf6f", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "16911b13ffc813228d0306d06966ac6060c7ed43dbb96160e35baf885d946e03", + "start_line": 1888, + "name": "current_url", + "arity": 2 + }, + "get_csrf_token/0:1440": { + "line": 1440, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 1440, + "ast_sha": "a1a7fbdee1275ae66c037393cab82aab4821740d0113fc8b0e081f1b3c6eca70", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "6d6ee0bf92f87e6896dcac0ced69c4df9b2daa5f0b2bd42ce0b0255fe1041615", + "start_line": 1440, + "name": "get_csrf_token", + "arity": 0 + }, + "__plugs__/2:1918": { + "line": 1918, + "guard": null, + "pattern": "controller_module, opts", + "kind": "def", + "end_line": 2006, + "ast_sha": "7f18430969dba92fb60b0d801faac66db06eb769f72c6e961fbf23baace47ad7", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "c4ed0e03037a322988efef4f2efc8b7f0c9880c8dce2491cdc4d475b831d6216", + "start_line": 1918, + "name": "__plugs__", + "arity": 2 + }, + "parse_exts/2:1601": { + "line": 1601, + "guard": null, + "pattern": "\"*\", \"*\"", + "kind": "defp", + "end_line": 1601, + "ast_sha": "1d236c42986020810311cc0996f2570a0a60287e5dccd1c14cc767deda1e96a5", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "bc500016da3ce6f2f09e89235d998fcdd68c2959e331ab211a594cbb66b03fa2", + "start_line": 1601, + "name": "parse_exts", + "arity": 2 + }, + "put_new_view/2:582": { + "line": 582, + "guard": "=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)", + "pattern": "%Plug.Conn{state: state} = conn, formats", + "kind": "def", + "end_line": 583, + "ast_sha": "33b4d5d68b5f0d8d09e9f287ca7b63aad21a943a7b9786edd7c678b397ae71ae", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9eed9dffa6eaa7409f4159f24916800493eb4ebeb9ac17fbd602901c30071cc6", + "start_line": 582, + "name": "put_new_view", + "arity": 2 + }, + "router_module/1:334": { + "line": 334, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 334, + "ast_sha": "b108d19169945a012245a7d4a9a1ce8c55eb2dbf58dda53837cec515fc72c151", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "64f2a3e0fbb1b2a1d46523d568ff5b72e80f681a49aca1b6ea87fc921a532026", + "start_line": 334, + "name": "router_module", + "arity": 1 + }, + "json/2:363": { + "line": 363, + "guard": null, + "pattern": "conn, data", + "kind": "def", + "end_line": 365, + "ast_sha": "f2a9ab311c7e12daa45c199f536b106b09236a6a16f5b3306b4d18242ab5b1e6", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "95f600480e5cdd2bd8892de9c268053de9e67a43ca63654d9084626022990ed8", + "start_line": 363, + "name": "json", + "arity": 2 + }, + "layout_formats/1:828": { + "line": 828, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 829, + "ast_sha": "34a3eab29a74bc0ace9066f517ac36a8c887e9d6d8ff8b28a4085b8b54108328", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "de01ae3f4d48089cf794a05cbe1304bea1a80e8d8a84a098e7d34cff2ae10dd3", + "start_line": 828, + "name": "layout_formats", + "arity": 1 + }, + "current_url/1:1842": { + "line": 1842, + "guard": null, + "pattern": "%Plug.Conn{} = conn", + "kind": "def", + "end_line": 1843, + "ast_sha": "b6ed35bac47ea731d0efe4c0922be0052bf52900b31654477d77238f025efc1b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "b40729934cb68d1c4fa99b233feb5d5f98a42cf4e4c9125fead6d84f243ddce1", + "start_line": 1842, + "name": "current_url", + "arity": 1 + }, + "parse_q/1:1588": { + "line": 1588, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 1596, + "ast_sha": "06b7277a46e1d131391c9eea8fe8f71a32979644ec4a2b44ddddbe2e0decd73b", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "8335dee45bceaa8d90633e73e683bb58c358579bea22871e8a93e4759143d8df", + "start_line": 1588, + "name": "parse_q", + "arity": 1 + }, + "action_name/1:322": { + "line": 322, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 322, + "ast_sha": "8b23412bbe4fb3ce552886fbd1132a4a88e6b3958d7eb17bd21716a9ff8d5215", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fe8211d23c7f21a827f3adac476728ce9f183decc5fb6cc6dce62459f3c3caff", + "start_line": 322, + "name": "action_name", + "arity": 1 + }, + "render/3:954": { + "line": 954, + "guard": "is_binary(template) and (is_map(assigns) or is_list(assigns))", + "pattern": "conn, template, assigns", + "kind": "def", + "end_line": 957, + "ast_sha": "10d2359d6a5f0ada2dc62f5d252b741f71b1a33daffb4ff330775a9d65799311", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "b29618e6c633eee39c91b6ccf3ac63005391fbea08b479a67a61174a46ac2639", + "start_line": 954, + "name": "render", + "arity": 3 + }, + "fetch_flash/2:1643": { + "line": 1643, + "guard": null, + "pattern": "conn, _opts", + "kind": "def", + "end_line": 1662, + "ast_sha": "93049ec766b4e8e4388e152621805fc612bfde1179d6ceec681bd043a501d01c", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e1b81807b94ccce0c42341105fff2acbbed37d985d841d6a00f029ea878b9d4f", + "start_line": 1643, + "name": "fetch_flash", + "arity": 2 + }, + "handle_params_accept/3:1531": { + "line": 1531, + "guard": null, + "pattern": "conn, format, accepted", + "kind": "defp", + "end_line": 1537, + "ast_sha": "67b8685287402ba56eab0c92a5616c33001f63abb4f5f0e437a85a711753b01a", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "00d29248f468fc59e5d0e35fbb798ebf0685470a4a293f1146f79c3ae3edc9bb", + "start_line": 1531, + "name": "handle_params_accept", + "arity": 3 + }, + "allow_jsonp/2:392": { + "line": 392, + "guard": null, + "pattern": "conn, opts", + "kind": "def", + "end_line": 411, + "ast_sha": "501554872c5b067cec74deb99d29484bc96ce8e3c5c1d38d0a6a76e0f21bec71", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "c26330230de0e57cca75bcc3383cfe27fc070115f62ed31cdb4404ac61c9445e", + "start_line": 392, + "name": "allow_jsonp", + "arity": 2 + }, + "scrub_param/1:1349": { + "line": 1349, + "guard": null, + "pattern": "%{} = param", + "kind": "defp", + "end_line": 1351, + "ast_sha": "9fc916d2b6e401b624fe4803f16685cc7262478955ba1448a02c8b37ed915988", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "8ef7791d21ed6dc239ee9318cdd30602c8ba9f93cfd5bbe684ce386dd98cb261", + "start_line": 1349, + "name": "scrub_param", + "arity": 1 + }, + "render_and_send/4:978": { + "line": 978, + "guard": null, + "pattern": "conn, format, template, assigns", + "kind": "defp", + "end_line": 985, + "ast_sha": "bcfbc1015c80b816b04ee40c16146a36a2de13bb209b656699343cf6a1a2afdd", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "b2e5e533e4dfa894845bd05778dc56920916f2a88a1b55c3d78a18c569d6a2e4", + "start_line": 978, + "name": "render_and_send", + "arity": 4 + }, + "split_template/1:1078": { + "line": 1078, + "guard": "is_atom(name)", + "pattern": "name", + "kind": "defp", + "end_line": 1078, + "ast_sha": "f310164c9ee809042a3a2aeaf2fb4e4aaef2d7a3c96535894fac9973441326b9", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "7c89cfff58b2034e5d0fd4eae3dc2e60d24dc881a950ebf81dea5077fc9ac3f0", + "start_line": 1078, + "name": "split_template", + "arity": 1 + }, + "get_private_layout/3:852": { + "line": 852, + "guard": null, + "pattern": "conn, priv_key, format", + "kind": "defp", + "end_line": 859, + "ast_sha": "c22a705d35aab3f85c7f7b62d40d5f22111e50298cf4fe3c8fc4171dcbe4384a", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "749852ea6965d63375bf453b24442a1cdbceea6a204c64a09c300eb2f1c5d33a", + "start_line": 852, + "name": "get_private_layout", + "arity": 3 + }, + "split_template/1:1080": { + "line": 1080, + "guard": "is_binary(name)", + "pattern": "name", + "kind": "defp", + "end_line": 1090, + "ast_sha": "9546273babaf6a2c2439a7b12ba083d00d0ccaca027b68658678f89c4b4b71db", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a5a820b6f5962cf6de44c814c906f7894cdc427aa360007c6d40eb7fa2a887d8", + "start_line": 1080, + "name": "split_template", + "arity": 1 + }, + "scrub?/1:1364": { + "line": 1364, + "guard": null, + "pattern": "\"\"", + "kind": "defp", + "end_line": 1364, + "ast_sha": "a8b940b641a1f26e7b41952124e13431c09a121f8f1dc414348935a32772e6df", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "5743bdb0858926c2b9927c4ff8b1075fef0ee91de102441c9ce054952351a836", + "start_line": 1364, + "name": "scrub?", + "arity": 1 + }, + "render/3:944": { + "line": 944, + "guard": "is_atom(template) and (is_map(assigns) or is_list(assigns))", + "pattern": "conn, template, assigns", + "kind": "def", + "end_line": 951, + "ast_sha": "e2e5c8ee9a0e3fc4f91f484b36e8aeeec73d56d0b6783ab5fb4bfe956924e665", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "1baf1a07ef065a5c3b3184d2bfe6054876cf9c00ceec77979c75a2d3779ef47f", + "start_line": 944, + "name": "render", + "arity": 3 + }, + "put_private_layout/4:665": { + "line": 665, + "guard": "is_list(layouts)", + "pattern": "conn, private_key, kind, layouts", + "kind": "defp", + "end_line": 702, + "ast_sha": "25ee9f829287d84aee04f22fb5af89419655f77fb9e3ba49ed7aa6d28045c70d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "ad82167fa2cca0797e6a7609af8df8158a5125522a4edbb80db50d793f2fe9ab", + "start_line": 665, + "name": "put_private_layout", + "arity": 4 + }, + "warn_if_ajax/1:1304": { + "line": 1304, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 1307, + "ast_sha": "9b3a774797f3e030140e4855323d5ed5d6c1f0fa57e101709ee98ec84e670e30", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "7aede4044ea71629e3da2bf651a962b3ecbb7308acfe0218d46651118cec19e4", + "start_line": 1304, + "name": "warn_if_ajax", + "arity": 1 + }, + "protect_from_forgery/1:1376": { + "line": 1376, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 1376, + "ast_sha": "417fbdde22fb1de7711161c85f9608a0e65dfef6427c33986a7e839b79a80146", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e355e6e3289879e6d41be064a75f382446940394d5b0b37b429964ada502ccfc", + "start_line": 1376, + "name": "protect_from_forgery", + "arity": 1 + }, + "put_static_url/2:1146": { + "line": 1146, + "guard": null, + "pattern": "conn, %URI{} = uri", + "kind": "def", + "end_line": 1147, + "ast_sha": "5e5acd9962e1a5d3eb2ae45367468e5756075d5096afb8f255f3aa2cb0e336a0", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9ffb35a2b26cf5e3810bb888f6b73bb0e5cada3f47b95d009ad6133c527da1c1", + "start_line": 1146, + "name": "put_static_url", + "arity": 2 + }, + "encode_filename/2:1285": { + "line": 1285, + "guard": null, + "pattern": "filename, true", + "kind": "defp", + "end_line": 1285, + "ast_sha": "09946eb278030dc45dff80cef34c6dc5ae11318cf9bf8175bb947cd9f09aa6d6", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "45c48d200d4d05a3d81704596f38acaafd6819387d2d63273399dffa2ee1c178", + "start_line": 1285, + "name": "encode_filename", + "arity": 2 + }, + "validate_jsonp_callback!/1:435": { + "line": 435, + "guard": "(is_integer(h) and (h >= 48 and =<(h, 57))) or (is_integer(h) and (h >= 65 and =<(h, 90))) or\n (is_integer(h) and (h >= 97 and =<(h, 122))) or h == 95", + "pattern": "<>", + "kind": "defp", + "end_line": 437, + "ast_sha": "2af79ce5e79b7d0b358c539d75b50335c5f14930443f682f7fe8b9786c501862", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "679ab5f001ce3f2ada7d36e23f474f59a523860421fd25610e476d6ca0ccf42b", + "start_line": 435, + "name": "validate_jsonp_callback!", + "arity": 1 + }, + "put_secure_defaults/1:1415": { + "line": 1415, + "guard": null, + "pattern": "%Plug.Conn{resp_headers: resp_headers} = conn", + "kind": "defp", + "end_line": 1431, + "ast_sha": "4cb6f01cbf7a57ac4643a329a5d4eb9eecc86f331ef0094d800e9306e62db18e", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "84326d2cde55901fc650594df43a3e37888654e6da4e3efba04809118e1af669", + "start_line": 1415, + "name": "put_secure_defaults", + "arity": 1 + }, + "clear_flash/1:1767": { + "line": 1767, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 1768, + "ast_sha": "9a6447e24f3100a27412ac532d6ee9eb45bfd6dceb0e1ac63104287dd76e5ed3", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "e06a43fd7da899bda23854c0a5dbcd7e438f99256f23849b1487b5d9c1cd2a81", + "start_line": 1767, + "name": "clear_flash", + "arity": 1 + }, + "root_layout/1:848": { + "line": 848, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 848, + "ast_sha": "f0e298915f706b2db841db4eee57f176c8015eb34c686cf6ad09aabfe2bd2f44", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fe055d911eb383f4044c80b8397b7f06e95712ce59af61b11acf2de275e1438f", + "start_line": 848, + "name": "root_layout", + "arity": 1 + }, + "assign/2:1915": { + "line": 1915, + "guard": null, + "pattern": "conn, assigns", + "kind": "def", + "end_line": 1915, + "ast_sha": "d80740a85de19f53e6c0fb2e6a36cd06963e53aae273a4f8116b869057473aa8", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "c4d4abe697c077b6f689a8129731b1e91ff9544c057decd8a02c31c1cee098d6", + "start_line": 1915, + "name": "assign", + "arity": 2 + }, + "put_private_view/4:557": { + "line": 557, + "guard": null, + "pattern": "conn, priv_key, kind, value", + "kind": "defp", + "end_line": 558, + "ast_sha": "d8cdf7196d8cf11d341d9d2ca8fcf4d9c9d3adfe7727736f7a386049547f5655", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "c2efb3f8c3f09588a887e3270479c4fc82821a160aff56c861d3b67bec0ecbad", + "start_line": 557, + "name": "put_private_view", + "arity": 4 + }, + "parse_header_accept/4:1575": { + "line": 1575, + "guard": null, + "pattern": "conn, [], acc, accepted", + "kind": "defp", + "end_line": 1579, + "ast_sha": "1730969df8a8754d1307e28925cf868372d687bae286d736f02990e029379315", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "81efc7a674d5896a019878132f7c24b89e8087ff0c745d04d9d6a22885ef794b", + "start_line": 1575, + "name": "parse_header_accept", + "arity": 4 + }, + "scrub_param/1:1355": { + "line": 1355, + "guard": "is_list(param)", + "pattern": "param", + "kind": "defp", + "end_line": 1356, + "ast_sha": "116091221aeffd70973eb626560003fe7c2afd72213f3e1980cf4e4162e00829", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "6116772eb1667c7a2e30607cab464d1c4449db4dc0144bed0cd968b6d98b6256", + "start_line": 1355, + "name": "scrub_param", + "arity": 1 + }, + "layout/1:838": { + "line": 838, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 838, + "ast_sha": "a3c71077a2eb244a109914816be1a541dbc72722aa23fc3bbcb44b88b51dcbad", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "164f03a758176229ac8438ec9a6904443b39a3485976a3a8bb8a2055e7c1f265", + "start_line": 838, + "name": "layout", + "arity": 1 + }, + "jsonp_body/2:425": { + "line": 425, + "guard": null, + "pattern": "data, callback", + "kind": "defp", + "end_line": 432, + "ast_sha": "1e16585cc501930b69cb1963d37da016675b3e04364bd4cebc051d396871221c", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "078bfedc70590e970d1990965bee0837b3d2fa1ad860a60b264afd5e8013edc3", + "start_line": 425, + "name": "jsonp_body", + "arity": 2 + }, + "validate_local_url/1:508": { + "line": 508, + "guard": null, + "pattern": "<<\"//\"::binary, _::binary>> = to", + "kind": "defp", + "end_line": 508, + "ast_sha": "7e29bb2b68ac353e3f89b3dbaf2c950fb6e22e94cc20565ea8197716e51fffb4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9fbd871aae6f1e1f999284d43ea0acb86297a0304115bfddc868a5aa19f2a4fe", + "start_line": 508, + "name": "validate_local_url", + "arity": 1 + }, + "expand_alias/2:258": { + "line": 258, + "guard": null, + "pattern": "other, _env", + "kind": "defp", + "end_line": 258, + "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", + "start_line": 258, + "name": "expand_alias", + "arity": 2 + }, + "layout/2:838": { + "line": 838, + "guard": null, + "pattern": "conn, format", + "kind": "def", + "end_line": 839, + "ast_sha": "f8e993e63d29de6c2cc7401ec3450cacb04aec457a4d42a1716da111e5e18bea", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9d49d83d09014d4d78ea45fc9345c292c405407fb7d7b68078352a6f72bb55d4", + "start_line": 838, + "name": "layout", + "arity": 2 + }, + "normalized_request_path/1:1830": { + "line": 1830, + "guard": null, + "pattern": "%{path_info: info, script_name: script}", + "kind": "defp", + "end_line": 1831, + "ast_sha": "e139df2f484eeec25c17a1ca541f3673d0198d8d9ed1fce8e993105abe22afed", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "707fd7b61e16ec98bc567e0d39da4efe8f25b16ba353b4508f68a3ddcc468dd2", + "start_line": 1830, + "name": "normalized_request_path", + "arity": 1 + }, + "put_secure_browser_headers/1:1403": { + "line": 1403, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 1403, + "ast_sha": "c360cc9db029904f1ae80547d1b509f20702614cae0cf615e61959b83b4c07d4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a0d39e0d147aedd748e7fb3d9c09ec30f87e5faeaa9ed54cb8ca1d6c5e88728c", + "start_line": 1403, + "name": "put_secure_browser_headers", + "arity": 1 + }, + "current_path/1:1790": { + "line": 1790, + "guard": null, + "pattern": "%Plug.Conn{query_string: \"\"} = conn", + "kind": "def", + "end_line": 1791, + "ast_sha": "5809befb206b65265e217f4a0a47ac707c17f3d6920a784115c4f051d3a39914", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "9241488e97168c79c7254c9165e273d0764b71eae05b71e12d6cf6f8880a6625", + "start_line": 1790, + "name": "current_path", + "arity": 1 + }, + "current_path/2:1826": { + "line": 1826, + "guard": null, + "pattern": "%Plug.Conn{} = conn, params", + "kind": "def", + "end_line": 1827, + "ast_sha": "8cb27effecdcef6cd2e963eed61c8a78d3e5295b8ec23f09ad766785b3c4bfc4", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "eaaadf2226d57f139e2894a396b0f610e3ec40ad5b20f2a6842e36cc71bd0423", + "start_line": 1826, + "name": "current_path", + "arity": 2 + }, + "render/3:960": { + "line": 960, + "guard": "is_atom(view) and (is_binary(template) or is_atom(template))", + "pattern": "conn, view, template", + "kind": "def", + "end_line": 966, + "ast_sha": "70ddddbf2297085caa7ffe9c8207aa1f43c53f6f3e97685e28fd2bae0c6e2ccf", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "a4cd40557eeedc1640adaacc5bc9d4f2f37dc793aeff20e5187344757de24360", + "start_line": 960, + "name": "render", + "arity": 3 + }, + "flash_key/1:1772": { + "line": 1772, + "guard": "is_atom(atom)", + "pattern": "atom", + "kind": "defp", + "end_line": 1772, + "ast_sha": "2a7a1d0af29abd0bf4c4abdb618dd31ebc512f75a61fa7eb1544b56601a94bfc", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "ed19748fb1a427f6db29c8f5870d640716c8c01bf31c2fdf0958a0452dba31e4", + "start_line": 1772, + "name": "flash_key", + "arity": 1 + }, + "put_secure_browser_headers/2:1409": { + "line": 1409, + "guard": "is_map(headers)", + "pattern": "conn, headers", + "kind": "def", + "end_line": 1412, + "ast_sha": "6a36dcee1a3e5661bc6af3514901b52cb9d13c601df6143b0a0effafb506e033", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "7a10f35b5857c38324a00a2a370f5b5acda643d590c0972e319c3b2c0d3fb582", + "start_line": 1409, + "name": "put_secure_browser_headers", + "arity": 2 + }, + "scrub_param/1:1359": { + "line": 1359, + "guard": null, + "pattern": "param", + "kind": "defp", + "end_line": 1360, + "ast_sha": "cbc013d72090fcde2b878d861c7b7e95cf79e03d2b572058ca9f54527f248228", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "f3057a82f7804d4753ff3f48635515c7a1ed5f795075a16bc54db81cb880f0c1", + "start_line": 1359, + "name": "scrub_param", + "arity": 1 + }, + "encode_filename/2:1284": { + "line": 1284, + "guard": null, + "pattern": "filename, false", + "kind": "defp", + "end_line": 1284, + "ast_sha": "6720c0d36d9da3a53ae834a791b14d3c34b5b30049f619ee077c1f7edcc93502", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "fbdd4f1fb1b17a37faf3aa3936c97943f870cc82075683696c84406734926ce1", + "start_line": 1284, + "name": "encode_filename", + "arity": 2 + }, + "expand_alias/2:255": { + "line": 255, + "guard": null, + "pattern": "{:__aliases__, _, _} = alias, env", + "kind": "defp", + "end_line": 256, + "ast_sha": "14682cc624c36e71add79f5dda8643559feb44d59953f72e99bff25a6eb48f56", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "544e138d90d94520a4b56cf0d154fa795a6efa6dabf3ee662ebe659611dbc92c", + "start_line": 255, + "name": "expand_alias", + "arity": 2 + }, + "delete_csrf_token/0:1447": { + "line": 1447, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 1447, + "ast_sha": "bfbbbfbf40052e78fe56fefc9e05a6019921872ae52f896bbcc27bfd2a946bc0", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "2454c660cb1d4b78433c75774c1ada05f1ade465e655d95971b940bfa669ddbf", + "start_line": 1447, + "name": "delete_csrf_token", + "arity": 0 + }, + "persist_flash/2:1774": { + "line": 1774, + "guard": null, + "pattern": "conn, value", + "kind": "defp", + "end_line": 1775, + "ast_sha": "7d508fbc9dc8efa8afb0897ee1d483e0b1177ff74772a94a1e35dbd48a98c881", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "53729114a6d61675ff04507137e4c04eab729f8e7c7c1bd1a62bc782b707f00d", + "start_line": 1774, + "name": "persist_flash", + "arity": 2 + }, + "endpoint_module/1:340": { + "line": 340, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 340, + "ast_sha": "25c57886dff9672794edc565d9222218879b25187b189b0acbfca5af3357582d", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "3c406b281d92af193feb1bd84729d507b6cd28412a3edada86f50f87b5b07762", + "start_line": 340, + "name": "endpoint_module", + "arity": 1 + }, + "parse_exts/2:1603": { + "line": 1603, + "guard": null, + "pattern": "type, subtype", + "kind": "defp", + "end_line": 1603, + "ast_sha": "78329193b65df3c14b83ee3af9bee4c29aea7fa933f91d8f0eb87de6fd9eef88", + "source_file": "lib/phoenix/controller.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", + "source_sha": "6dc2f6ae9a4969f1da8405793bff02fb122f57ab697c9d553bb39d5cd89a645d", + "start_line": 1603, + "name": "parse_exts", + "arity": 2 + } + }, + "Phoenix.Param.Float": { + "__impl__/1:70": { + "line": 70, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 70, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "447a95046f2237b38d953cdb1dcf49b7b25be4043395a4c9446462456ae6865a", + "start_line": 70, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:71": { + "line": 71, + "guard": null, + "pattern": "float", + "kind": "def", + "end_line": 71, + "ast_sha": "16b840a66bcac7054a9817879985cc789dc9470f1ae80b81bf3863d0016a573e", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "ebd010a07494298469ba4811f4816b766234a1d277a17a2f912e6d1584b6b62c", + "start_line": 71, + "name": "to_param", + "arity": 1 + } + }, + "Phoenix.Endpoint.Watcher": { + "cd/1:59": { + "line": 59, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 59, + "ast_sha": "090c3e472461a3bc77b4b5a1559d9814eeadceff2decaa3d1a730a928adcf3c6", + "source_file": "lib/phoenix/endpoint/watcher.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", + "source_sha": "dcf7eb1f91c1b485c8302457ab12bb00a68de9c27a618f80b7474de148d28dda", + "start_line": 59, + "name": "cd", + "arity": 1 + }, + "start_link/1:13": { + "line": 13, + "guard": null, + "pattern": "{cmd, args}", + "kind": "def", + "end_line": 14, + "ast_sha": "3babca99d59ca9bdf47711f2ec57d4d66f02ae4cacd1352aa494ccc7983064e7", + "source_file": "lib/phoenix/endpoint/watcher.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", + "source_sha": "6334e5063f163ed7be119a5494ae079319b341b46e4d03d7e4be1d58e41dbe43", + "start_line": 13, + "name": "start_link", + "arity": 1 + }, + "watch/2:17": { + "line": 17, + "guard": null, + "pattern": "_cmd, {mod, fun, args}", + "kind": "def", + "end_line": 27, + "ast_sha": "8968d235362f977803df63b7633afb606046f9f929627392c7cf2572a4121386", + "source_file": "lib/phoenix/endpoint/watcher.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", + "source_sha": "4ecdff5ede7d6a7a6a8414c80d0716410c44e0293dacba819cf62e089d243322", + "start_line": 17, + "name": "watch", + "arity": 2 + }, + "watch/2:31": { + "line": 31, + "guard": "is_list(args)", + "pattern": "cmd, args", + "kind": "def", + "end_line": 55, + "ast_sha": "4b827ca8b5bbce1e6a3df74be2bd08e2629cd061aa57ad5b52ab7b39e8388f39", + "source_file": "lib/phoenix/endpoint/watcher.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", + "source_sha": "513b0022e814a388872db99d84db5c77bb915c7df7c336ffa6cbe71092044d50", + "start_line": 31, + "name": "watch", + "arity": 2 + } + }, + "Mix.Tasks.Phx.Gen.Socket": { + "paths/0:113": { + "line": 113, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 113, + "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", + "start_line": 113, + "name": "paths", + "arity": 0 + }, + "raise_with_help/0:82": { + "line": 82, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 83, + "ast_sha": "db992a2f2b807e24c0021de430484b2f378852f947e538fa77e013ee80376ca2", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "afdfd3e5d30e0557dfdb9989299a9d0d52b3bc25de29f7c935ba5ea7d84db0d2", + "start_line": 82, + "name": "raise_with_help", + "arity": 0 + }, + "run/1:28": { + "line": 28, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 77, + "ast_sha": "3c4d1cea79a42054176b3500024898eee098f685fb5099db2d73a18126796480", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "dbd65b22ad80bcf21d57f466410c74ccbf158b068a178b9e3238938ced0edb43", + "start_line": 28, + "name": "run", + "arity": 1 + }, + "valid_name?/1:109": { + "line": 109, + "guard": null, + "pattern": "name", + "kind": "defp", + "end_line": 110, + "ast_sha": "116909eba9bf97ce2ec07a574ff6b32373f50a44f2af12b8e78e5a5bb51ebd17", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "6f11947844b4c7b3c737756284b91e5cf8fd88aa20d29257704fcd75a6a6e3ec", + "start_line": 109, + "name": "valid_name?", + "arity": 1 + }, + "validate_args!/1:107": { + "line": 107, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 107, + "ast_sha": "b7b4237b9a81f05dbe1f0cc5a0382bb38ebc3593f62bb4ba09dfe27512839627", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "eff2ea8fce27f866c70fab6574ddf30433b00959ba444b5538a0232d0df29bf7", + "start_line": 107, + "name": "validate_args!", + "arity": 1 + }, + "validate_args!/1:91": { + "line": 91, + "guard": null, + "pattern": "[name, \"--from-channel\", pre_existing_channel]", + "kind": "defp", + "end_line": 96, + "ast_sha": "1357d1ddd6b0c30ff071a0f141b2a64b638fcc1de9183936f4f82a0edd02bc85", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "a246f406bd97024f57f95ab90104c5eb33b9639a55fca1133e99260d2d835317", + "start_line": 91, + "name": "validate_args!", + "arity": 1 + }, + "validate_args!/1:99": { + "line": 99, + "guard": null, + "pattern": "[name]", + "kind": "defp", + "end_line": 104, + "ast_sha": "5d4951905121016be9e3c9e81d51cc1569e8ec94c522dc809ca3f21dacfc701b", + "source_file": "lib/mix/tasks/phx.gen.socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", + "source_sha": "28a6df1710e338c1831885628e675409340a7b3366a3258daae09c7485e50e7d", + "start_line": 99, + "name": "validate_args!", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": { + "build/1:13": { + "line": 13, + "guard": null, + "pattern": "\"bcrypt\"", + "kind": "def", + "end_line": 23, + "ast_sha": "3f32e30001742b4216918ee00a3de8a8fc485c177af2f43e8312e6031268b8e8", + "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_sha": "904da9edf6b27ebe0a3c73582971ba84d0f2b6ffebf42c5555915ab7508d1121", + "start_line": 13, + "name": "build", + "arity": 1 + }, + "build/1:26": { + "line": 26, + "guard": null, + "pattern": "\"pbkdf2\"", + "kind": "def", + "end_line": 36, + "ast_sha": "65f8dbec91247b6ebbe02e05e3b3dd591b1597ed6d6d6d163d1cc1db605aa013", + "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_sha": "e6478506b29e912d187aaddb1353d2277b83fd1aecd7278fabef606ac219bb9e", + "start_line": 26, + "name": "build", + "arity": 1 + }, + "build/1:39": { + "line": 39, + "guard": null, + "pattern": "\"argon2\"", + "kind": "def", + "end_line": 49, + "ast_sha": "2688a8e1b96e9adf5680651792e22f0c305bb8ae0a87ee07da6f57201491e13b", + "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_sha": "8c91b2da263b93e3cb727788efea447d093c56263d713eccdd5e0e3655c0141c", + "start_line": 39, + "name": "build", + "arity": 1 + }, + "build/1:52": { + "line": 52, + "guard": null, + "pattern": "other", + "kind": "def", + "end_line": 53, + "ast_sha": "fb79f1d77fc94e6a4a3bb14bd0ae9c39a00cc6ce0b08f8524acd64fd120669df", + "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", + "source_sha": "ba4044406f0198445934f0b070ba02501124951bc8813367b1e4bba165a8f785", + "start_line": 52, + "name": "build", + "arity": 1 + } + }, + "Phoenix.Router.NoRouteError": { + "exception/1:8": { + "line": 8, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 16, + "ast_sha": "988fe8857827b216447b4e000a82ae02cac4ab8a3dbaf6fa20ac8a6bfd4b57ec", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "e1e48344b11cafaeaf332a567fe604cf96951a8d3262f4ae27f42dab97fa38b6", + "start_line": 8, + "name": "exception", + "arity": 1 + }, + "message/1:6": { + "line": 6, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 6, + "ast_sha": "51a2b9a745170c7e0700a65970170ef43382cc9b888edd9a4bdd2e656f5c3054", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "6ec747094a43bd6423990fa0574c42ea1ae3ba2ebd10a7a144091f89d14b017e", + "start_line": 6, + "name": "message", + "arity": 1 + } + }, + "Phoenix.Router.Helpers": { + "defhelper/2:250": { + "line": 250, + "guard": null, + "pattern": "%Phoenix.Router.Route{} = route, exprs", + "kind": "def", + "end_line": 265, + "ast_sha": "d753381d36d29c1d536669fecc44807d07dee199c3b0b14ce340f9fe6ad6cb7f", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "d2202fc501484c818c3fa7e7a2dfd868e71537b4665f8914a586b418d74dbd46", + "start_line": 250, + "name": "defhelper", + "arity": 2 + }, + "defhelper_catch_all/1:270": { + "line": 270, + "guard": null, + "pattern": "{helper, routes_and_exprs}", + "kind": "def", + "end_line": 298, + "ast_sha": "2b7c71907372d686e357da577ec7608fc99d1b54362337a16ff5c67db8b3a495", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "f92bd07e6175801ebd3c08e448e4f2d6950d4b1d98774f757d8a58abd077949c", + "start_line": 270, + "name": "defhelper_catch_all", + "arity": 1 + }, + "define/2:11": { + "line": 11, + "guard": null, + "pattern": "env, routes", + "kind": "def", + "end_line": 242, + "ast_sha": "2f5deb05fcfd989763cf633df052ac2de79df51795e63a708bb0c8dfca7483e5", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "8d7bb1b12f9487b463611cb493b41fbb70ce6e118e269e0b74c94ad8e8412f8d", + "start_line": 11, + "name": "define", + "arity": 2 + }, + "encode_param/1:350": { + "line": 350, + "guard": null, + "pattern": "str", + "kind": "def", + "end_line": 350, + "ast_sha": "781fcd9652340ae51f0c8d8bacd7062e62d00f5735bdd0e27a313e1f306d5786", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "15645be3d40fa3cdf66f88746d5e7a8682d3306ffb9dcb90a48a81ccc1ef9ca2", + "start_line": 350, + "name": "encode_param", + "arity": 1 + }, + "expand_segments/1:352": { + "line": 352, + "guard": null, + "pattern": "[]", + "kind": "defp", + "end_line": 352, + "ast_sha": "bdad58ab17a09c6000f23a8bcb6a806be3e7b5eab8c758543057b4257e2a4286", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "999de31b9fe8753d5a71a86ea88e200e02ecfea1d68b6bc8edb18bdeac3428cd", + "start_line": 352, + "name": "expand_segments", + "arity": 1 + }, + "expand_segments/1:354": { + "line": 354, + "guard": "is_list(segments)", + "pattern": "segments", + "kind": "defp", + "end_line": 355, + "ast_sha": "4afc402f946fd61855d509de1be2a317a0a48cdcb18f07755db6e376282949fa", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "57da7ff6218a06e0d2d4cb1beb7139cd2db4d9e764579bd3b589eb23911f0d67", + "start_line": 354, + "name": "expand_segments", + "arity": 1 + }, + "expand_segments/1:358": { + "line": 358, + "guard": null, + "pattern": "segments", + "kind": "defp", + "end_line": 359, + "ast_sha": "fb55ffad7f96c6af963eab1cac40f00a00b88a59f84ab3ef3bdbaad6e0e11333", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "7df1e56facb6b9c2ab7e17e93307557955211049a6f2cb0d744aeb9c4fe135c0", + "start_line": 358, + "name": "expand_segments", + "arity": 1 + }, + "expand_segments/2:362": { + "line": 362, + "guard": null, + "pattern": "[{:|, _, [h, t]}], acc", + "kind": "defp", + "end_line": 367, + "ast_sha": "fb31dd992c067a369e462318d2b8f4e239804f571b612fb03c5d8772b1b352d3", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "5de292998f8fa2222f00a2e4475dceab850dabb22cb59e7c72f780d650b8a1a4", + "start_line": 362, + "name": "expand_segments", + "arity": 2 + }, + "expand_segments/2:370": { + "line": 370, + "guard": "is_binary(h)", + "pattern": "[h | t], acc", + "kind": "defp", + "end_line": 371, + "ast_sha": "bd52db5cbc10743b8f8b7b988b7a93797972b9f5fdbe75a0d3b804aae2a016b3", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "d70c1e064a7d11307393bc2daaf60f97e20a330af30028442d973792458902ac", + "start_line": 370, + "name": "expand_segments", + "arity": 2 + }, + "expand_segments/2:373": { + "line": 373, + "guard": null, + "pattern": "[h | t], acc", + "kind": "defp", + "end_line": 377, + "ast_sha": "e61c0c7819bda27b1f649145f9d57fa6116bad97b9554a320b9b3e94b7be4b28", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "b51ad2d008c490cb89e2b0eb5355dff516c1739a8aa643d625571becc3ac9aa0", + "start_line": 373, + "name": "expand_segments", + "arity": 2 + }, + "expand_segments/2:380": { + "line": 380, + "guard": null, + "pattern": "[], acc", + "kind": "defp", + "end_line": 381, + "ast_sha": "138cce8fb555f568f9d4969efdae1f464677a889ec1e51dfcebf2b7f4c24884f", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "9fee30bf80f0648ad23bd26fc13d58c17022ce0734273e9ad87af5d019260dbd", + "start_line": 380, + "name": "expand_segments", + "arity": 2 + }, + "invalid_param_error/5:332": { + "line": 332, + "guard": null, + "pattern": "mod, fun, arity, action, routes", + "kind": "defp", + "end_line": 340, + "ast_sha": "089098dcba4f5d44e793907eb0b8dcdaba66c1661f9e80101229592cbc69b19a", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "05cca0a26ebd5ad623b3bcde94e733bf62509247365ce86518dac1086dc593e7", + "start_line": 332, + "name": "invalid_param_error", + "arity": 5 + }, + "invalid_route_error/3:321": { + "line": 321, + "guard": null, + "pattern": "prelude, fun, routes", + "kind": "defp", + "end_line": 329, + "ast_sha": "2c51aa70a7cb8857cccada14cb84ab133c273d56d51446022bd606a40c0c1bcb", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "db4c4d782b56a41b2bfca097b62647c3d4612a80ed735e75f0864cf82038425e", + "start_line": 321, + "name": "invalid_route_error", + "arity": 3 + }, + "raise_route_error/6:306": { + "line": 306, + "guard": null, + "pattern": "mod, fun, arity, action, routes, params", + "kind": "def", + "end_line": 317, + "ast_sha": "aadb04f816a752ed46cd8a7d6047734fd82f8b4d33fde709f4838fa006cca2de", + "source_file": "lib/phoenix/router/helpers.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", + "source_sha": "b251107818d7306b619d0576f57b63d847cfe5181956c306ed60568ccbfb1f16", + "start_line": 306, + "name": "raise_route_error", + "arity": 6 + } + }, + "Phoenix.CodeReloader.Proxy": { + "child_spec/1:5": { + "line": 5, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 862, + "ast_sha": "d39d628946704cac279bb034b010ec426bb9a2f87c3667d921acf068e9346a7f", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "e4c2bc0f72c378111f17c3560f067711433dae27efbe607a74b147c584fb26ab", + "start_line": 5, + "name": "child_spec", + "arity": 1 + }, + "code_change/3:5": { + "line": 5, + "guard": null, + "pattern": "_old, state, _extra", + "kind": "def", + "end_line": 940, + "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "e4c2bc0f72c378111f17c3560f067711433dae27efbe607a74b147c584fb26ab", + "start_line": 5, + "name": "code_change", + "arity": 3 + }, + "diagnostic_to_chars/1:61": { + "line": 61, + "guard": null, + "pattern": "%{severity: :error, message: <<\"**\"::binary, _::binary>> = message}", + "kind": "defp", + "end_line": 62, + "ast_sha": "b649d98180fea9acc7bd1a877710222ef7854a0da73df235b010b94c321e1969", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "4d6751ca9faa4f287bce540c6c6c12ff73622fc87093bf23f3add4143fc938f8", + "start_line": 61, + "name": "diagnostic_to_chars", + "arity": 1 + }, + "diagnostic_to_chars/1:65": { + "line": 65, + "guard": "is_binary(file)", + "pattern": "%{severity: severity, message: message, file: file, position: position}", + "kind": "defp", + "end_line": 66, + "ast_sha": "f33d2324c07ff10008accd9952b47caeba5468cacbe727a099eda5709f60220c", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "f3e4017bc69d152c813b227e8e607bbfa82dbba0932a0009b8702e7069e6e80b", + "start_line": 65, + "name": "diagnostic_to_chars", + "arity": 1 + }, + "diagnostic_to_chars/1:69": { + "line": 69, + "guard": null, + "pattern": "%{severity: severity, message: message}", + "kind": "defp", + "end_line": 70, + "ast_sha": "bf102a678d9f3620494b736d2325cda9e3f125dd00b2be0f8b6e652294eb6595", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "fde584b706b8688f04d0a165c96df5014e50ae9e23d330319832d61801322436", + "start_line": 69, + "name": "diagnostic_to_chars", + "arity": 1 + }, + "diagnostics/2:11": { + "line": 11, + "guard": null, + "pattern": "proxy, diagnostics", + "kind": "def", + "end_line": 12, + "ast_sha": "9e78d2b9914d3d6945dc58726397cb81f23fa3d9be2542d961d51d31e260e848", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "4c670ede84a89965015389ccbdcceda1393ea26d0b0392a260e3f0d4ae63f363", + "start_line": 11, + "name": "diagnostics", + "arity": 2 + }, + "handle_call/3:29": { + "line": 29, + "guard": null, + "pattern": ":stop, _from, output", + "kind": "def", + "end_line": 30, + "ast_sha": "cfbe95b9150c1914519df4ef1a83139ec4b9416c528924b81a7df7212be0813a", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "5b7e841683db5546800e88f34fd2260801d1dba8a38d39dbba9a2c45c79a0a3d", + "start_line": 29, + "name": "handle_call", + "arity": 3 + }, + "handle_cast/2:25": { + "line": 25, + "guard": null, + "pattern": "{:diagnostics, diagnostics}, output", + "kind": "def", + "end_line": 26, + "ast_sha": "c79c133927c80dcf4d1ae47f9e105fdc92fb65c17508aaa638423b14e76d1377", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "f05971575c039fcfb7e32ebc186e3da6708a884c785c44328372c2b1c79691ca", + "start_line": 25, + "name": "handle_cast", + "arity": 2 + }, + "handle_info/2:33": { + "line": 33, + "guard": null, + "pattern": "msg, output", + "kind": "def", + "end_line": 52, + "ast_sha": "e9147d3c9c0341e572e9b534ab36f2688e26c65097ae25f35ee32fc9fb07b0b9", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "a0d5c28991aa1ea17eb6bf49bc1c0963a1c02b8f9e4e09a89202335121b930a8", + "start_line": 33, + "name": "handle_info", + "arity": 2 + }, + "init/1:21": { + "line": 21, + "guard": null, + "pattern": ":ok", + "kind": "def", + "end_line": 21, + "ast_sha": "1333ab1920c76e3b15e016d4aaf48b7d42e235e282199ec0d070d9efda509748", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "66bd5ffb86957db83e516b90a67f1c99358bce4382ac5ce2d9128aa45d92fd89", + "start_line": 21, + "name": "init", + "arity": 1 + }, + "position/1:73": { + "line": 73, + "guard": null, + "pattern": "{line, col}", + "kind": "defp", + "end_line": 73, + "ast_sha": "177fb2267f686456337c3ab08ba8f98f8c47ed815c463cf0b0960fac50e710b5", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "57fa0844cbf4e09e840a80e21c3527107a78aa4b94efef19779995a366e29a0a", + "start_line": 73, + "name": "position", + "arity": 1 + }, + "position/1:74": { + "line": 74, + "guard": "is_integer(line) and line > 0", + "pattern": "line", + "kind": "defp", + "end_line": 74, + "ast_sha": "685d54a23dbaabf240d35388fa37a53de0bc25e3239f5ac1052bebb8610f09f7", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "00f00123830d91520a83ffd556ffed679be46d30c853c35e6cd4ef743cf17a61", + "start_line": 74, + "name": "position", + "arity": 1 + }, + "position/1:75": { + "line": 75, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 75, + "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "d6f7b129b37e6565fc95d462cf6b01756fcfbadd22f0fc13efd929dfff26fe98", + "start_line": 75, + "name": "position", + "arity": 1 + }, + "put_chars/4:56": { + "line": 56, + "guard": null, + "pattern": "from, reply, chars, output", + "kind": "defp", + "end_line": 58, + "ast_sha": "a422d404cb3134418ec99761807c93908a3042dab446ef38c7aae93564ed96d7", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "115c0e82b24b88bffe526730b87193551ff82d7ead9fcbbba846ef83bc0c24b7", + "start_line": 56, + "name": "put_chars", + "arity": 4 + }, + "start/0:7": { + "line": 7, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 8, + "ast_sha": "1068fcdd9c8dccdbbac222ed0f19dffece400050c21288c471b7df4b46627c68", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "9943ad29f30d2483fc104784fc409c861a69891be038bdbd981e41e52e7e27bb", + "start_line": 7, + "name": "start", + "arity": 0 + }, + "stop/1:15": { + "line": 15, + "guard": null, + "pattern": "proxy", + "kind": "def", + "end_line": 16, + "ast_sha": "0668bfa31d09f13697951d49b0206405b49360d8a6e4f6000bc05bec351802ea", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "2e35e474ee5c3e3465c583585a9ce58302fac0acb4fdd727a3d4401ffde5f366", + "start_line": 15, + "name": "stop", + "arity": 1 + }, + "terminate/2:5": { + "line": 5, + "guard": null, + "pattern": "_reason, _state", + "kind": "def", + "end_line": 5, + "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", + "source_file": "lib/phoenix/code_reloader/proxy.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", + "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", + "start_line": 5, + "name": "terminate", + "arity": 2 + } + }, + "Phoenix.ActionClauseError": { + "__struct__/0:47": { + "line": 47, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 47, + "ast_sha": "0fc0146830ec1659e91eaade37d7a373aeddb8ede37faa33e1ba540633ea32fd", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", + "start_line": 47, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:47": { + "line": 47, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 47, + "ast_sha": "df77ef2167ef692ea2294b1e2d1e2c5daad0841d6d52269566a7c50aa3a06506", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", + "start_line": 47, + "name": "__struct__", + "arity": 1 + }, + "blame/2:57": { + "line": 57, + "guard": null, + "pattern": "exception, stacktrace", + "kind": "def", + "end_line": 65, + "ast_sha": "e6b5582e09c4675d7a4ef92da1d882a761c6b6c35c994374ad42a45a604f221e", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "6df6865bf2b6db488bb027ba10726ccde97f58747cf8fe5b79fc2e3fc8383b99", + "start_line": 57, + "name": "blame", + "arity": 2 + }, + "exception/1:47": { + "line": 47, + "guard": "is_list(args)", + "pattern": "args", + "kind": "def", + "end_line": 47, + "ast_sha": "b604e12ac1ef01393bc4b1f1415c7c50743e32117df6cf4843d7ffa0a2346cf3", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", + "start_line": 47, + "name": "exception", + "arity": 1 + }, + "message/1:50": { + "line": 50, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 53, + "ast_sha": "82050b73f3c8907643c3b17591a4c900e4a695b9fb4519e6a9bff003cf3f400c", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "59f06ee6f7b308a0f6b254398319c4b5b89f72a10ebfb05902e07269c88c2b96", + "start_line": 50, + "name": "message", + "arity": 1 + } + }, + "Phoenix.Socket": { + "user_connect/6:622": { + "line": 622, + "guard": null, + "pattern": "handler, endpoint, transport, serializer, params, connect_info", + "kind": "defp", + "end_line": 676, + "ast_sha": "50bf50998ff9ae42839655c3dee465ed3d14067ebeceea2feeef3d0cf7420d12", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "510d9958cc34e505e97735deb2b80ac3b0d913a3ae718bdbf245a9db320452df", + "start_line": 622, + "name": "user_connect", + "arity": 6 + }, + "encode_reply/2:838": { + "line": 838, + "guard": null, + "pattern": "%{serializer: serializer}, message", + "kind": "defp", + "end_line": 840, + "ast_sha": "657e86aae8e96a9f28e2ddc5b4aeaa09eb085d1ae20b8fce7977ea7c86cabe1c", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "f198d05d038f4e5356e533592dd2cf948c3743522d3e71b178692e208b3c7f4f", + "start_line": 838, + "name": "encode_reply", + "arity": 2 + }, + "handle_in/4:695": { + "line": 695, + "guard": null, + "pattern": "nil, %{event: \"phx_join\", topic: topic, ref: ref, join_ref: join_ref} = message, state, socket", + "kind": "defp", + "end_line": 730, + "ast_sha": "5107e6a577043defff9147e1801625be2e956f7a9c4e3581e943a5c551259062", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "cf3802585731950bce0e654c720161118369135a8b113f5a6b463df5e2a9bfcb", + "start_line": 695, + "name": "handle_in", + "arity": 4 + }, + "channel/3:397": { + "line": 397, + "guard": null, + "pattern": "topic_pattern, module, opts", + "kind": "defmacro", + "end_line": 408, + "ast_sha": "d315cc956e55202f2cbdd04b256f7a9f1798dae897c61abd25c6ab68b4ece91e", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "b75f2e2dea3c41e0826c70f20acb6733bf8ed2edfa44f7ca344847787b8d93e8", + "start_line": 397, + "name": "channel", + "arity": 3 + }, + "__info__/2:562": { + "line": 562, + "guard": null, + "pattern": ":socket_drain, state", + "kind": "def", + "end_line": 564, + "ast_sha": "ea289c3336b85517c7d20ea3acd8756f02af9e88ea04c385e44e60ac764f37c0", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "13d602a078b9f62f1dcd02116a50ad3c1ab1ba61ea759eb785ec0c97ec0ca1d8", + "start_line": 562, + "name": "__info__", + "arity": 2 + }, + "socket_close/2:868": { + "line": 868, + "guard": null, + "pattern": "pid, {state, socket}", + "kind": "defp", + "end_line": 876, + "ast_sha": "1390ce5511d100e606785c99c4b3aafa275244d012013645488abf21973eff24", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "eb4404f7aa7c3158271fe8bdc04d73fdd1eb7defb56eabc8f621c283bfb74978", + "start_line": 868, + "name": "socket_close", + "arity": 2 + }, + "set_label/1:531": { + "line": 531, + "guard": null, + "pattern": "socket", + "kind": "defp", + "end_line": 533, + "ast_sha": "3fe08f2dbb543fc29c11062214d9ef857f8e165a7e1911f8f84069d8d3776b3c", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "b942772b216b1e9b121fa2c8b6c6ab01413363f24d8cc84bb74cb4f698f41fd1", + "start_line": 531, + "name": "set_label", + "arity": 1 + }, + "to_topic_match/1:442": { + "line": 442, + "guard": null, + "pattern": "topic_pattern", + "kind": "defp", + "end_line": 446, + "ast_sha": "8bba8c0a877983cd0f445e15dd8417271cc13798e53636bc2952c58d2851fd82", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "44aa97be50773fa62b86c557cd32625c069b2e9699aa4e9ffad7d6738ddc8e70", + "start_line": 442, + "name": "to_topic_match", + "arity": 1 + }, + "expand_alias/2:412": { + "line": 412, + "guard": null, + "pattern": "{:__aliases__, _, _} = alias, env", + "kind": "defp", + "end_line": 413, + "ast_sha": "82c00e1b2e922270a189153b46db4973d0df716717df67cb9f27491a8088c9ff", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d910d5007abe499f9a53fe4beff3dfeeb71a706d9443fe2e87124362603281d7", + "start_line": 412, + "name": "expand_alias", + "arity": 2 + }, + "negotiate_serializer/2:598": { + "line": 598, + "guard": "is_list(serializers)", + "pattern": "serializers, vsn", + "kind": "defp", + "end_line": 617, + "ast_sha": "b76f3d227f323c9a42b5105d834c22bd2880069c092fe713a537415478b82666", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "0f2faeefd4a365153a1c86524a5da07b965c1b0553b64ab7ff785da411694fa4", + "start_line": 598, + "name": "negotiate_serializer", + "arity": 2 + }, + "__terminate__/2:594": { + "line": 594, + "guard": null, + "pattern": "_reason, _state_socket", + "kind": "def", + "end_line": 594, + "ast_sha": "206cec333f0a4f8ef4aac9354c8055e02ff9ebd0979518b17c29ad2c6c0ecf90", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "8f78f7cab4b48f26b9375469a3ec187c5ed225040e9d204d165f84e760c360cc", + "start_line": 594, + "name": "__terminate__", + "arity": 2 + }, + "put_channel/4:806": { + "line": 806, + "guard": null, + "pattern": "state, pid, topic, join_ref", + "kind": "defp", + "end_line": 813, + "ast_sha": "97e39f2fe08ec1d9fa87be6e81446596da94004f195e09871a159e790c7c3668", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "9718754f5e1f6748a947f2643291f54989c9ef8d4be78ea6f68ca7e4213a48e9", + "start_line": 806, + "name": "put_channel", + "arity": 4 + }, + "handle_in/4:734": { + "line": 734, + "guard": null, + "pattern": "{pid, _ref, status}, %{event: \"phx_join\", topic: topic} = message, state, socket", + "kind": "defp", + "end_line": 750, + "ast_sha": "d98cf16daa9f3f915303e996564fd7c4b9b107aa09121175e0ee65b722cecf93", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "522fe7ab449f5fb47ab0033ed95408bc2440bf6099c55999c49fe78dc121e5d7", + "start_line": 734, + "name": "handle_in", + "arity": 4 + }, + "__info__/2:571": { + "line": 571, + "guard": null, + "pattern": "{:socket_close, pid, _reason}, state", + "kind": "def", + "end_line": 572, + "ast_sha": "ec15a691354149d56bc87224f07f5e118e04c86ce4bfddd312eee2245083cdb0", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "108a402f0277c3be3967b2a6f75a5ab43a88c6b1fc716dfa2a6ee8fed85a336a", + "start_line": 571, + "name": "__info__", + "arity": 2 + }, + "expand_alias/2:415": { + "line": 415, + "guard": null, + "pattern": "other, _env", + "kind": "defp", + "end_line": 415, + "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", + "start_line": 415, + "name": "expand_alias", + "arity": 2 + }, + "__before_compile__/1:423": { + "line": 423, + "guard": null, + "pattern": "env", + "kind": "defmacro", + "end_line": 437, + "ast_sha": "3dd7ff8e077ee898a9f89f31f87ebb382ba4f99b9085147efb6a7e19bb289a13", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "6420a94f90c92c39abb7e23c71eaa35b10c3be3c14b518d7f647cf7115c37292", + "start_line": 423, + "name": "__before_compile__", + "arity": 1 + }, + "assign/2:362": { + "line": 362, + "guard": "is_map(keyword_or_map) or is_list(keyword_or_map)", + "pattern": "%Phoenix.Socket{} = socket, keyword_or_map", + "kind": "def", + "end_line": 364, + "ast_sha": "ad90868d8912a9daad38e22b8ebeb1da3824f61ca0ac4d28aa610e0e388c16a0", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "4152cffd3df519d7742886ac03e37c02bf53a9ff390517f12395594a40795604", + "start_line": 362, + "name": "assign", + "arity": 2 + }, + "__struct__/1:257": { + "line": 257, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 257, + "ast_sha": "f649eca2bee634cfd528e4b8354fb08d5a046888513f8785f441ee973f4eda7e", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "e60eea24791c55c319855ad886eae033c9597db77c90f6397c58c34d4fb01c25", + "start_line": 257, + "name": "__struct__", + "arity": 1 + }, + "__info__/2:558": { + "line": 558, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{event: \"disconnect\"}, state", + "kind": "def", + "end_line": 559, + "ast_sha": "0818be9e3e9bdd8460ccd4319ac15295538a503f931b7c44330c555eabf10bf3", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d1a2b3dba28c0979bd566b77b0dbcf350429024031f9ba3006b261049d39b08b", + "start_line": 558, + "name": "__info__", + "arity": 2 + }, + "update_channel_status/4:880": { + "line": 880, + "guard": null, + "pattern": "state, pid, topic, status", + "kind": "defp", + "end_line": 882, + "ast_sha": "0e0ac0e98831f9356936a84e39f04ad4dbc2e1feb4a460089fffbbca6134e1dc", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "5919524c48a921e9c26d41d3c29553b0f21cac46ea63b64854efac4bacf046f6", + "start_line": 880, + "name": "update_channel_status", + "arity": 4 + }, + "__info__/2:580": { + "line": 580, + "guard": null, + "pattern": "{:debug_channels, ref, reply_to}, {state, socket}", + "kind": "def", + "end_line": 587, + "ast_sha": "bf5b38bf379b232824ed04931402bd47471ea2c11e02a40e48d432c5a964d82d", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "cf5373bd5814202e09f4e9eb70686859cc05378876b47ae66c3f94f2fda72b0a", + "start_line": 580, + "name": "__info__", + "arity": 2 + }, + "__struct__/0:257": { + "line": 257, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 257, + "ast_sha": "4fe472087621da2629bb451dd5ad5182c4bf4ba96fea314f9b6870b059675f17", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "e60eea24791c55c319855ad886eae033c9597db77c90f6397c58c34d4fb01c25", + "start_line": 257, + "name": "__struct__", + "arity": 0 + }, + "__info__/2:567": { + "line": 567, + "guard": null, + "pattern": "{:socket_push, opcode, payload}, state", + "kind": "def", + "end_line": 568, + "ast_sha": "c083e72058b94eabb77cf05dbd6aecaed8d342cae67426fee886e828760047e4", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "00881cd0ba44c6a7a5eaba161c6b927a805cb6be527bfff0534e02de8b18fa9f", + "start_line": 567, + "name": "__info__", + "arity": 2 + }, + "handle_in/4:768": { + "line": 768, + "guard": null, + "pattern": "{pid, _ref, _status}, msg, state, socket", + "kind": "defp", + "end_line": 779, + "ast_sha": "f2f07fb5eab23450b41094c9e1f400023060b04f8b469bb375aae1c1cb7a477d", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "a3099a22c3e309a51508599a7ad200b4345cbfb13b2c79b5532e88290755fc2e", + "start_line": 768, + "name": "handle_in", + "arity": 4 + }, + "assign/2:367": { + "line": 367, + "guard": "is_function(fun, 1)", + "pattern": "%Phoenix.Socket{} = socket, fun", + "kind": "def", + "end_line": 368, + "ast_sha": "5dec69379ffb3d3521abff6e1fcfa139dc7c1b484377408f29e50b741311bec0", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "282a050974e43c838edda53911a02755e2fe45baa895452212c4de33f8109055", + "start_line": 367, + "name": "assign", + "arity": 2 + }, + "__child_spec__/3:458": { + "line": 458, + "guard": null, + "pattern": "handler, opts, socket_options", + "kind": "def", + "end_line": 463, + "ast_sha": "02f8b72d2f79274f92e83607d9b4e183ee3496fbcd8f6b3de54b0c6b3b049edb", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "22aa442453db5f0f431ff87762eeca07323e6eda7c4613779fd67dc5c183648f", + "start_line": 458, + "name": "__child_spec__", + "arity": 3 + }, + "defchannel/3:450": { + "line": 450, + "guard": null, + "pattern": "topic_match, channel_module, opts", + "kind": "defp", + "end_line": 452, + "ast_sha": "c057e1815f2cef51edf85f71dd91b787b191d658865a6f539aa9fb29c29fcdf4", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "e46a9998bf631d13493869de673066baedecc4fc0449bb49ea059d3b70d15225", + "start_line": 450, + "name": "defchannel", + "arity": 3 + }, + "encode_ignore/2:833": { + "line": 833, + "guard": null, + "pattern": "socket, %{ref: ref, topic: topic}", + "kind": "defp", + "end_line": 835, + "ast_sha": "a5098c3df66d0a4282be16a02ead510601e55e025aee7135c6510940b990050f", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "59629af6ad47a6ca4ccc8feaec7b7f4185858413be5084b5b6c83d68a511984d", + "start_line": 833, + "name": "encode_ignore", + "arity": 2 + }, + "handle_in/4:753": { + "line": 753, + "guard": null, + "pattern": "{pid, _ref, _status}, %{event: \"phx_leave\"} = msg, state, socket", + "kind": "defp", + "end_line": 764, + "ast_sha": "7656f1f50c958a786ec00b4be92ee19122ea1de94072f2b39a74a6eb45f6b763", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "232440c0bd5394ac44897e36366cec5a73fc129ecb140116188505a996b806dc", + "start_line": 753, + "name": "handle_in", + "arity": 4 + }, + "__using__/1:290": { + "line": 290, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 298, + "ast_sha": "1a0d647674d3ec79622a36b9e149f52eb529357a41f8948eaec98a2b65dc2370", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "0a8ac0c1e3d9d335c2a7477a5f8753362a62bdb73d2a62f134dccfc003253b37", + "start_line": 290, + "name": "__using__", + "arity": 1 + }, + "assign/3:342": { + "line": 342, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket, key, value", + "kind": "def", + "end_line": 343, + "ast_sha": "b6f4572dbf953a6bc43033beb7afd70982114e8ec4fc11b89e0a9a85e84c3af1", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d701c1fc97f889703e7452edfc64510fa6d1268491d46ebff488ff7cc9286d13", + "start_line": 342, + "name": "assign", + "arity": 3 + }, + "transport/3:419": { + "line": 419, + "guard": null, + "pattern": "_name, _module, _config", + "kind": "defmacro", + "end_line": 419, + "ast_sha": "4c8b6da0dc80be17d3eb95dacaf4bceaed3c7844bce2fee7aff2b076a8c95422", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "0632dfdb3a0fe67fa0e8bbcded930e2c3078d954cbc1adac2969914040b0a41f", + "start_line": 419, + "name": "transport", + "arity": 3 + }, + "result/1:529": { + "line": 529, + "guard": null, + "pattern": "{:error, _}", + "kind": "defp", + "end_line": 529, + "ast_sha": "f20d11584b9475f1553b95ee4e5feafcc87ca44d116dd4bf743a0943d983b40c", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "2509ab75c4d1bff2980dc29a7a069f707fbe5910ef30a4daa6f023c35099c2c5", + "start_line": 529, + "name": "result", + "arity": 1 + }, + "__info__/2:575": { + "line": 575, + "guard": null, + "pattern": ":garbage_collect, state", + "kind": "def", + "end_line": 577, + "ast_sha": "a4ee1aab516d6e8b107adb305182cf208978385eb6a7bc5b94508b7fa522ad9b", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "0c02a499c046d24da69f179b4b5007c19c5fbbf2a73285e42872a311d7b03398", + "start_line": 575, + "name": "__info__", + "arity": 2 + }, + "handle_in/4:684": { + "line": 684, + "guard": null, + "pattern": "_, %{ref: ref, topic: \"phoenix\", event: \"heartbeat\"}, state, socket", + "kind": "defp", + "end_line": 692, + "ast_sha": "4077788f1c2a5e0da0a44e4a08c563c92186d49a4a668fea4cf9c7f659d917c6", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "8651f7dd6e14514253594797cb31507afb8dbea47e6d6afb091c57b131649db4", + "start_line": 684, + "name": "handle_in", + "arity": 4 + }, + "delete_channel/4:817": { + "line": 817, + "guard": null, + "pattern": "state, pid, topic, monitor_ref", + "kind": "defp", + "end_line": 824, + "ast_sha": "2fa094bb970b313d518dd3f9c0c9b69bc7d66200bcc68b017bea776d0dc27ca6", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "f29c15cf11bf5732605afc3ae3a8f1ab1623e94b273a55ac86fb20995c4045ba", + "start_line": 817, + "name": "delete_channel", + "arity": 4 + }, + "handle_in/4:783": { + "line": 783, + "guard": null, + "pattern": "nil, %{event: \"phx_leave\", ref: ref, topic: topic, join_ref: join_ref}, state, socket", + "kind": "defp", + "end_line": 797, + "ast_sha": "74f5476b928d44b9632451094c795e3f485e53b37770e8c58890d3b24f988ff1", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "e732262dca1443293c126a9f547a964eebf957fdb6282cef6d9023253a4e3197", + "start_line": 783, + "name": "handle_in", + "arity": 4 + }, + "__drainer_spec__/3:466": { + "line": 466, + "guard": null, + "pattern": "handler, opts, socket_options", + "kind": "def", + "end_line": 482, + "ast_sha": "c70791190634f22c84517b45ac62a5a6ea0683e7ca39084325d886c38e91318d", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "290ff6ca9fda2ad2d1933c608876c449b182941fdcb5597902bffaca1cb5d4f7", + "start_line": 466, + "name": "__drainer_spec__", + "arity": 3 + }, + "result/1:528": { + "line": 528, + "guard": null, + "pattern": ":error", + "kind": "defp", + "end_line": 528, + "ast_sha": "275536599397a6bb53631c3a0c687e558e4f47b7dd28414e9b2e105b25a48be7", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "a9852de8b6fd992023a1c8966eea4c7c325889560787bc779c77fe56f83354a0", + "start_line": 528, + "name": "result", + "arity": 1 + }, + "result/1:527": { + "line": 527, + "guard": null, + "pattern": "{:ok, _}", + "kind": "defp", + "end_line": 527, + "ast_sha": "a93b9923b29170761a8ba926d2f71cb06c7887e177d34d07844065f8935fec43", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "9199e1dccb9bd475f5b5c6f0a1b124359cd27a52e34458f44b525b869a4b9084", + "start_line": 527, + "name": "result", + "arity": 1 + }, + "channel/2:397": { + "line": 397, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 397, + "ast_sha": "0a71ff97caac2170228be47baca7ce80ac9fd2b40ff8c1a225882e4871de9203", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "dc111ee6521b2960bb1853b34ef4a4f128b32b6404f212a948e2c3f737783047", + "start_line": 397, + "name": "channel", + "arity": 2 + }, + "__connect__/3:488": { + "line": 488, + "guard": null, + "pattern": "user_socket, map, socket_options", + "kind": "def", + "end_line": 522, + "ast_sha": "c59513d5a3369ff336baa7814951f0e298b0c7aac459f6081774c082715a2046", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d894e0e07a1a20a10f024898ebf9681fba9af5521f8af479dd778ebe1e954323", + "start_line": 488, + "name": "__connect__", + "arity": 3 + }, + "__info__/2:590": { + "line": 590, + "guard": null, + "pattern": "_, state", + "kind": "def", + "end_line": 591, + "ast_sha": "befa2369a21a2819de00ca6c3deb97e278f59f96ebe731b8a9c9222d561cd121", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "411f7ec81367cb9c4a87c63fe8ec1d1b16880df779743f4041bb471d3ea5f6d0", + "start_line": 590, + "name": "__info__", + "arity": 2 + }, + "shutdown_duplicate_channel/1:855": { + "line": 855, + "guard": null, + "pattern": "pid", + "kind": "defp", + "end_line": 864, + "ast_sha": "db0d7d9463147e6ba02907a9d713b5113e37c18bd296e272c34e1a2f43abec4f", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "ba661781b66129201b1f2dac396c39115c78e2aa8ba4aabd2a1fa2a4f6bda4f8", + "start_line": 855, + "name": "shutdown_duplicate_channel", + "arity": 1 + }, + "handle_in/4:800": { + "line": 800, + "guard": null, + "pattern": "nil, message, state, socket", + "kind": "defp", + "end_line": 803, + "ast_sha": "001427cb73fdada3df639826e8277143ffde6da0ac8a3cf4ce48278bc65b1afd", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "159b08315805c2e706dae7e542ec04c830ab558f87a66e0d6e0587b375cc2167", + "start_line": 800, + "name": "handle_in", + "arity": 4 + }, + "__in__/2:542": { + "line": 542, + "guard": null, + "pattern": "{payload, opts}, {state, socket}", + "kind": "def", + "end_line": 544, + "ast_sha": "ee37802fc88f4089dd3a04e7b8c5f41611e4d55f5597d771fb946f51825884b1", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "056d6bb54537e8b32afe375d1a4895fd40340a1d264364a472e8333da7390ee9", + "start_line": 542, + "name": "__in__", + "arity": 2 + }, + "__info__/2:547": { + "line": 547, + "guard": null, + "pattern": "{:DOWN, ref, _, pid, reason}, {state, socket}", + "kind": "def", + "end_line": 554, + "ast_sha": "2432914dcdee220291c63e8c14b045a323a5f5d082e708b23c61f3bd3c40ce93", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "b5c25f4c52db6112acc31c31ee1187b0ef318d4323613a76e2152a840255f5e4", + "start_line": 547, + "name": "__info__", + "arity": 2 + }, + "transport/2:419": { + "line": 419, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 419, + "ast_sha": "c9aea0b46e577fe17d27eb82eaffe854bf18c4bd75128cab38eb6a48272a204a", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "0632dfdb3a0fe67fa0e8bbcded930e2c3078d954cbc1adac2969914040b0a41f", + "start_line": 419, + "name": "transport", + "arity": 2 + }, + "__init__/1:536": { + "line": 536, + "guard": null, + "pattern": "{state, %{id: id, endpoint: endpoint} = socket}", + "kind": "def", + "end_line": 539, + "ast_sha": "6dfa463d9d6d4712956cb96c36f129e480fe0e167f48bbd08800ea13a3660f0c", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "410eff737ce1dd10b5b319c6d72f3aed49739a748a0749cccbc1492f5aabddaa", + "start_line": 536, + "name": "__init__", + "arity": 1 + }, + "encode_close/3:843": { + "line": 843, + "guard": null, + "pattern": "socket, topic, join_ref", + "kind": "defp", + "end_line": 852, + "ast_sha": "77fe0170b8b0ab05ca3d6b05418f7b95a8e5c26bf63cf4bb42fb0a7eea6f09d1", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "554231a5b6efbebfac50812d35d6598cc60021afe86f204a8a0f0cd5172bd618", + "start_line": 843, + "name": "encode_close", + "arity": 3 + }, + "encode_on_exit/4:828": { + "line": 828, + "guard": null, + "pattern": "socket, topic, ref, _reason", + "kind": "defp", + "end_line": 830, + "ast_sha": "fd0be6b6cad4fc4f9685848f13ae6f51f9793a1c2914ae5dc98b65f18d890582", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "e4fd12d4930de9f4b83803c5702195dfeb3559a06e23dabccb251d17fc63d393", + "start_line": 828, + "name": "encode_on_exit", + "arity": 4 + } + }, + "Phoenix.Digester.Gzip": { + "compress_file/2:7": { + "line": 7, + "guard": null, + "pattern": "file_path, content", + "kind": "def", + "end_line": 9, + "ast_sha": "43ac78ad17d605c1c2769068259c34cadf65916da828778cb9f06776135ef6d1", + "source_file": "lib/phoenix/digester/gzip.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester/gzip.ex", + "source_sha": "466360c4ea839c2c1d311544a1cf90a3c2cbefd0b9cfeba8f340436a17d4af18", + "start_line": 7, + "name": "compress_file", + "arity": 2 + }, + "file_extensions/0:15": { + "line": 15, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 15, + "ast_sha": "8873827b20bb040f20e74a7cc92a53569d1bcb1d333dff4f4345828fe8a34513", + "source_file": "lib/phoenix/digester/gzip.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester/gzip.ex", + "source_sha": "503bb1ca84a6fa92fa037631264b10495ec14f75b7341c9e30a5899024ca86b5", + "start_line": 15, + "name": "file_extensions", + "arity": 0 + } + }, + "Phoenix": { + "json_library/0:47": { + "line": 47, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 48, + "ast_sha": "f53a34ba4f6e517bd7588e8165d18b510f2e450729a8e6e7d648725c7345ec75", + "source_file": "lib/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "source_sha": "12f9fb90bce89a9cae2ceecc4c1e25e301540bb38a156db6c434f35833a231e7", + "start_line": 47, + "name": "json_library", + "arity": 0 + }, + "plug_init_mode/0:61": { + "line": 61, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 62, + "ast_sha": "6ab4cd9e2da1ae6e801e577595f0088788f7f2ed23a7691ca554a6a49fffdc8a", + "source_file": "lib/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "source_sha": "9b0f1c25bae1be6f2ca36a6306c3e93945dd8d1b76da93117a4b10d09cbba898", + "start_line": 61, + "name": "plug_init_mode", + "arity": 0 + }, + "start/2:10": { + "line": 10, + "guard": null, + "pattern": "_type, _args", + "kind": "def", + "end_line": 35, + "ast_sha": "84fea3994d539fdb36cebdb7dd1a59ddb0caaa5b574566d4756fafae84ad51a4", + "source_file": "lib/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "source_sha": "6295dd6b82e9bc652ad5d33645c491480a6556d12fa0f752cd2bb6aeaacdb876", + "start_line": 10, + "name": "start", + "arity": 2 + }, + "stop/1:7": { + "line": 7, + "guard": null, + "pattern": "_state", + "kind": "def", + "end_line": 7, + "ast_sha": "09fe6e37b419a2fab24e390e3208139125f69da76332b3936618bbe4aba75bdb", + "source_file": "lib/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "source_sha": "644a30f07bb3dda540830b2cdb68554d53633551dd3787e8ee28b211c6b8c7b7", + "start_line": 7, + "name": "stop", + "arity": 1 + }, + "warn_on_missing_json_library/0:65": { + "line": 65, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 72, + "ast_sha": "4d343c6745b1e86f35b3ff7b6aa2dc217f4daa1a1d809fb487565b443b11826f", + "source_file": "lib/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", + "source_sha": "6642c17afba5de65d0dbc3bbc8fc3e13a5c35d58f1dd0923a1aa53151edf0de6", + "start_line": 65, + "name": "warn_on_missing_json_library", + "arity": 0 + } + }, + "Mix.Tasks.Phx.Gen.Channel": { + "paths/0:118": { + "line": 118, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 118, + "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", + "source_file": "lib/mix/tasks/phx.gen.channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", + "start_line": 118, + "name": "paths", + "arity": 0 + }, + "raise_with_help/0:97": { + "line": 97, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 98, + "ast_sha": "f540f7db0ebd112912d17a857338bbf2f0b02a000d4736fedd043c28c79268e9", + "source_file": "lib/mix/tasks/phx.gen.channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "source_sha": "afdfd3e5d30e0557dfdb9989299a9d0d52b3bc25de29f7c935ba5ea7d84db0d2", + "start_line": 97, + "name": "raise_with_help", + "arity": 0 + }, + "valid_name?/1:114": { + "line": 114, + "guard": null, + "pattern": "name", + "kind": "defp", + "end_line": 115, + "ast_sha": "c83c3a804cce744198355059e76845ea33d69386df3ddf0fcdbdc5dbb27fec90", + "source_file": "lib/mix/tasks/phx.gen.channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "source_sha": "6f11947844b4c7b3c737756284b91e5cf8fd88aa20d29257704fcd75a6a6e3ec", + "start_line": 114, + "name": "valid_name?", + "arity": 1 + }, + "validate_args!/1:106": { + "line": 106, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 111, + "ast_sha": "08e664382ac7c13ced6a99544f6de7384061733b4b6f29ff9c7a95eed4d18c0e", + "source_file": "lib/mix/tasks/phx.gen.channel.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", + "source_sha": "c363e9384baff9d465dd2bd0415896e94eeea5c509c56742db6633ef81b95410", + "start_line": 106, + "name": "validate_args!", + "arity": 1 + } + }, + "Phoenix.Socket.Transport": { + "host_to_binary/1:652": { + "line": 652, + "guard": null, + "pattern": "{:system, env_var}", + "kind": "defp", + "end_line": 652, + "ast_sha": "fd2778b21966cabc3331dfc919aeee3c5998662ee9d271610e2296c995c48e55", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "06135c36fd39f1fdbe33ca15c51ff20ed357624a256b594b48cdc7b7ab67f9ee", + "start_line": 652, + "name": "host_to_binary", + "arity": 1 + }, + "check_subprotocols/2:399": { + "line": 399, + "guard": null, + "pattern": "%Plug.Conn{halted: true} = conn, _subprotocols", + "kind": "def", + "end_line": 399, + "ast_sha": "7b8670013439598b1f8e50fbd23e0f7703268e470f40d7087e5056993888b3a3", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "858214eba5e1053a0d2fc70cb26738c3febbfb3eecbe5b4478bd72a3dee81872", + "start_line": 399, + "name": "check_subprotocols", + "arity": 2 + }, + "fetch_headers/2:535": { + "line": 535, + "guard": null, + "pattern": "conn, prefix", + "kind": "defp", + "end_line": 538, + "ast_sha": "6b097d89a32f58bfa27026a8c8fc97cfac0121e247aedd3ee4e591b884f9ee3c", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "d0230fdbf4776038363b790e7b1ea0107b29513279c2d23aab9392811b9e5ef6", + "start_line": 535, + "name": "fetch_headers", + "arity": 2 + }, + "compare_host?/2:648": { + "line": 648, + "guard": null, + "pattern": "request_host, allowed_host", + "kind": "defp", + "end_line": 649, + "ast_sha": "633f05474b64437c26f47424195cdf2a62a8d4c51e4af791bb48da8f5b7ee6c9", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "cf40d5a1fe49a9016205cfe8765f21e7b515adcd26343246e4124d9f73428a1f", + "start_line": 648, + "name": "compare_host?", + "arity": 2 + }, + "compare_host?/2:645": { + "line": 645, + "guard": null, + "pattern": "request_host, <<\"*.\"::binary, allowed_host::binary>>", + "kind": "defp", + "end_line": 646, + "ast_sha": "f41c3112509cae8d96a60c40cf60a61ab87adeee09051dbec3ec5ffb0a8702ee", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "66e5d228db7fb86029a5e2d717dff97c5468a30a91005fb20aa15e05d84ac105", + "start_line": 645, + "name": "compare_host?", + "arity": 2 + }, + "origin_allowed?/4:622": { + "line": 622, + "guard": null, + "pattern": "true, uri, endpoint, _conn", + "kind": "defp", + "end_line": 623, + "ast_sha": "20a92fff970104588887219e8651f4ac61b64af9c139b75f46593056d35e84a2", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "11db20408a9b0b03ec7f02dd2e0840a8d27b27e9fe47fb12cc5fab7bf0871980", + "start_line": 622, + "name": "origin_allowed?", + "arity": 4 + }, + "check_subprotocols/2:400": { + "line": 400, + "guard": null, + "pattern": "conn, nil", + "kind": "def", + "end_line": 400, + "ast_sha": "4e8519273addb0b1417c32122610eed910e40f389be8aeb024763d6e567589c2", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "cd5308f68c5729e611c14b3aa93c46ef05289574c38c4dacf6b5b7965fd14c97", + "start_line": 400, + "name": "check_subprotocols", + "arity": 2 + }, + "origin_allowed?/4:613": { + "line": 613, + "guard": null, + "pattern": ":conn, uri, _endpoint, %Plug.Conn{} = conn", + "kind": "defp", + "end_line": 616, + "ast_sha": "389155eba67dfdba850d0fe8ee59e9429a3da3b48debc9088f6ece013f71b812", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "8439c719340bc89105fcea77c202b83829251bdc79d76718be28cc59e8b6f5c9", + "start_line": 613, + "name": "origin_allowed?", + "arity": 4 + }, + "check_origin/5:343": { + "line": 343, + "guard": null, + "pattern": "conn, handler, endpoint, opts, sender", + "kind": "def", + "end_line": 382, + "ast_sha": "6fe1ac0d839051aaa1b17aa1a4b4ae6eea3a3a28be9fdad734c891e326e336a6", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "bf0de1ae84e6f7df8ce36fd4d3e6db979d341c198a426f8afa37c9a47e8880b1", + "start_line": 343, + "name": "check_origin", + "arity": 5 + }, + "compare?/2:638": { + "line": 638, + "guard": null, + "pattern": "request_val, allowed_val", + "kind": "defp", + "end_line": 639, + "ast_sha": "c56ff87d620f5ad6877a1a6995d8e51afe209f898e820421e277f28d8ead48bf", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "2c46c93aa5ee4b75f9a65034b84e9528f0eeeb30ec0a2b884a60e33f205a1f1f", + "start_line": 638, + "name": "compare?", + "arity": 2 + }, + "compare_host?/2:642": { + "line": 642, + "guard": null, + "pattern": "_request_host, nil", + "kind": "defp", + "end_line": 642, + "ast_sha": "9e8d178a9777dfd5b4870c16eb1fc2c1a94f10cf4686bdd1d0de611ee92113ef", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "af789848da0449c38a3ce4e4179c493214798ea0bdba17edb3c06325e1fe2c24", + "start_line": 642, + "name": "compare_host?", + "arity": 2 + }, + "init_session/1:292": { + "line": 292, + "guard": "is_list(session_config)", + "pattern": "session_config", + "kind": "defp", + "end_line": 297, + "ast_sha": "30f42eac4425e7013216fb85ebdc91123553e9c54cd696b8e26ad9a835ac92c9", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "646a0dd8551cdaf0ef833b9e3cf1aca0796e73cd55d4ab9a5329aad57544ca48", + "start_line": 292, + "name": "init_session", + "arity": 1 + }, + "fetch_uri/1:547": { + "line": 547, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 554, + "ast_sha": "bba0a8cd573a6d0514be967ffee3cfb7e4183a00eee65760a8511b783a94d470", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "8f3916e4281a2aa3370bd6fc6db24e95805a7a5f5c91a53c8b66069726ef6f73", + "start_line": 547, + "name": "fetch_uri", + "arity": 1 + }, + "connect_info/3:477": { + "line": 477, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 477, + "ast_sha": "544e2ebb11b86ce0e5d1a56aadc21cb40acb30fcfbda40659d1563136894c12b", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "d801c426349759d1544157df02a36ae6cb43698506e29f81fb325ec64934f844", + "start_line": 477, + "name": "connect_info", + "arity": 3 + }, + "check_subprotocols/2:402": { + "line": 402, + "guard": "is_list(subprotocols)", + "pattern": "conn, subprotocols", + "kind": "def", + "end_line": 416, + "ast_sha": "8ea3a28b04460eb3ec9569d12ab20c8174c97d4fe0c756b13d09b894d6b37898", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "b176bbaee68abad8160ad63261f367404e3d3506beab030a479630a8a940a05c", + "start_line": 402, + "name": "check_subprotocols", + "arity": 2 + }, + "subprotocols_error_response/2:423": { + "line": 423, + "guard": null, + "pattern": "conn, subprotocols", + "kind": "defp", + "end_line": 451, + "ast_sha": "d2cd671a0e1e28853ee41f4d308d050adc618b1b583e8341413e449b2f6e24a1", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "e13fa61d93c37deef9a24b1a1909ebb05bd3998232c81d20953c63911dfa464a", + "start_line": 423, + "name": "subprotocols_error_response", + "arity": 2 + }, + "origin_allowed?/4:625": { + "line": 625, + "guard": "is_list(check_origin)", + "pattern": "check_origin, uri, _endpoint, _conn", + "kind": "defp", + "end_line": 626, + "ast_sha": "97cc44042ae0b4ba7dca73f2a23268ec62405888e06fbfae2206b7cc1c9fd17a", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "b4894134157716de6ae61a3ee585e0fafdaac54eeb36e5fc4f7c5cbac7e0d292", + "start_line": 625, + "name": "origin_allowed?", + "arity": 4 + }, + "check_origin/4:338": { + "line": 338, + "guard": null, + "pattern": "x0, x1, x2, x3", + "kind": "def", + "end_line": 338, + "ast_sha": "8d672323f6bae716c1211565ab9f7775dc8dd23d6771f92d1adb5c0efd594481", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "4d3c5ed3099b11c66cdab5bb859d903c7f61161dc78af783391f810ff83197ba", + "start_line": 338, + "name": "check_origin", + "arity": 4 + }, + "init_session/1:300": { + "line": 300, + "guard": null, + "pattern": "{_, _, _} = mfa", + "kind": "defp", + "end_line": 301, + "ast_sha": "5e77b62f89f20aebd0f53e49b407167057a12828c38456bf8328bfb9be867f99", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "888d7fd6c9da4969a337b58dcb7a3200eedb25a53c4bc03991006feed6cccbf7", + "start_line": 300, + "name": "init_session", + "arity": 1 + }, + "host_to_binary/1:653": { + "line": 653, + "guard": null, + "pattern": "host", + "kind": "defp", + "end_line": 653, + "ast_sha": "fcc6e42a3178691cc48b853962a3394fe692fb40382672cd3ed333809f8bfc0e", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "5c1f211fed7786a4ce62803ec43b1ba6368132b8316e3013254c6cb6acf4d2dd", + "start_line": 653, + "name": "host_to_binary", + "arity": 1 + }, + "transport_log/2:320": { + "line": 320, + "guard": null, + "pattern": "conn, level", + "kind": "def", + "end_line": 324, + "ast_sha": "dd12a6777356764c5c6561ead713b56cf06c887d00e5d6699089e334099bd80d", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "46f17972171c13c890ed60e0cfd21b5cc856b76bbe887f8f8e908596199b189a", + "start_line": 320, + "name": "transport_log", + "arity": 2 + }, + "load_config/1:259": { + "line": 259, + "guard": null, + "pattern": "config", + "kind": "def", + "end_line": 287, + "ast_sha": "745287617380910b8002a8ccbd698e940f77f2125b263d9b0a2d5f6b3ffb95af", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "51aae811929b3114071495ac7a4763940f7be37655f85d49e410e98f7d02e8ba", + "start_line": 259, + "name": "load_config", + "arity": 1 + }, + "origin_allowed?/4:619": { + "line": 619, + "guard": null, + "pattern": "_check_origin, %{host: nil}, _endpoint, _conn", + "kind": "defp", + "end_line": 619, + "ast_sha": "ae5a995df6fadae24ee7dc349bb4b91509f9fedfe5437c19250643bd2250b28a", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "704da459fc1676bae3eaf9083913c5d0dc9e0424a090239e03c315c858651f7a", + "start_line": 619, + "name": "origin_allowed?", + "arity": 4 + }, + "origin_allowed?/2:628": { + "line": 628, + "guard": null, + "pattern": "uri, allowed_origins", + "kind": "defp", + "end_line": 634, + "ast_sha": "c6122dc08b1fd9c0db79cc5e75ecb11a96356a9d5a6540ebe95f2624685915b4", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "8b26b01c2256e8035b44b42ccab4ed0e0992d92f4fa3fa714db623757e26e38c", + "start_line": 628, + "name": "origin_allowed?", + "arity": 2 + }, + "load_config/2:255": { + "line": 255, + "guard": null, + "pattern": "config, module", + "kind": "def", + "end_line": 256, + "ast_sha": "9800d75d24fa40ef97664018362026816c5fb459c0ec1250b978ffee77fdd626", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "4c334732fa4b800cfcecc354d43b65614b15f024159c08a5a62061f92ccf59b5", + "start_line": 255, + "name": "load_config", + "arity": 2 + }, + "connect_info/4:477": { + "line": 477, + "guard": null, + "pattern": "conn, endpoint, keys, opts", + "kind": "def", + "end_line": 505, + "ast_sha": "7541e2b52c13d7886a0d07ffd97b444dde6784e9e303f1693c380c4373153d65", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "da043cf87961fec862b42b365375a064a11d2af31a9eeb74c4cebf58a3234748", + "start_line": 477, + "name": "connect_info", + "arity": 4 + }, + "check_subprotocols/2:421": { + "line": 421, + "guard": null, + "pattern": "conn, subprotocols", + "kind": "def", + "end_line": 421, + "ast_sha": "218ae1a83a1737fa045069d6aaab4b3dbfce77f2b581961b495eff430122b9f9", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "130c0e07053042001b2693472ff93cf9ed9adce9b5ddb03cf92b3c990fb08c53", + "start_line": 421, + "name": "check_subprotocols", + "arity": 2 + }, + "origin_allowed?/4:610": { + "line": 610, + "guard": null, + "pattern": "{module, function, arguments}, uri, _endpoint, _conn", + "kind": "defp", + "end_line": 611, + "ast_sha": "9f06e60b6e38be41e4bb5c3d633a3fccc20818867eb18a5261084a7f6c91f24c", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "773c740f09e92bb019f4a6f5acaa9c864d311383831c0fbbd81a0839049b3db4", + "start_line": 610, + "name": "origin_allowed?", + "arity": 4 + }, + "load_config/2:252": { + "line": 252, + "guard": null, + "pattern": "true, module", + "kind": "def", + "end_line": 253, + "ast_sha": "60d848556f057edda5a0692b7ca606e7232fa7b94ad0866c39af4da1cb59e347", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "78512d45fb4548e8034177a68272804368a6e3a61e93ea97c98ad7da02f72cea", + "start_line": 252, + "name": "load_config", + "arity": 2 + }, + "fetch_trace_context_headers/1:541": { + "line": 541, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 544, + "ast_sha": "6155d2457023cee8d122814130421699840a8e1fbf776267378b1124c5b17bba", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "9d559a8291be8b8b0e111bc1e7fb4995b5b65c3f679079e668fc6427bea55519", + "start_line": 541, + "name": "fetch_trace_context_headers", + "arity": 1 + }, + "code_reload/3:307": { + "line": 307, + "guard": null, + "pattern": "conn, endpoint, opts", + "kind": "def", + "end_line": 312, + "ast_sha": "62d4188b0ff7f4cf42012e4d8c08f1236d029ead81bf393508e4aa780cfba38d", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "c2d8fb5c279337e3a3d4d7c30c9614b0a7d92f9c75ac5b607169f572bcc29212", + "start_line": 307, + "name": "code_reload", + "arity": 3 + }, + "connect_session/4:524": { + "line": 524, + "guard": null, + "pattern": "conn, endpoint, {:mfa, {module, function, args}}, opts", + "kind": "defp", + "end_line": 531, + "ast_sha": "e103c3ba223e9962976286fcd01aacffd1ba11dedbd41d3003630dc08aaabb39", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "cd5bc0ecbba54c0d6e795bc30794115f9ad35d464bd68acb87233b7e168cd2b9", + "start_line": 524, + "name": "connect_session", + "arity": 4 + }, + "connect_session/4:510": { + "line": 510, + "guard": null, + "pattern": "conn, endpoint, {key, store, {csrf_token_key, init}}, opts", + "kind": "defp", + "end_line": 520, + "ast_sha": "7b3d5c04a4aac63c97c52c7acc7bd7f92952aa0e4d2795f7219972a5d064ab95", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "efb1f135bcd631272821c2df257bd49c6d6156ae89082f647be2ceb170363032", + "start_line": 510, + "name": "connect_session", + "arity": 4 + }, + "fetch_user_agent/1:558": { + "line": 558, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 560, + "ast_sha": "552e3109fbd70f9decc237c97fdfa0133aa9e7b0d97fb24f3142f168494ad000", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "a295ddb4a7c24682d8bbd29370279b1785d1e9c41e099e98edab2ef9b1bada69", + "start_line": 558, + "name": "fetch_user_agent", + "arity": 1 + }, + "check_origin/5:340": { + "line": 340, + "guard": null, + "pattern": "%Plug.Conn{halted: true} = conn, _handler, _endpoint, _opts, _sender", + "kind": "def", + "end_line": 341, + "ast_sha": "b563ead2a4fcb1b4a890ec6da951408fbc3eca4f6422c7b8d7a317dfb17058e9", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "548d598cf4ba8607fb3ce0b5acea632cfb789e93bee3d401d5b91b77b5258c99", + "start_line": 340, + "name": "check_origin", + "arity": 5 + }, + "parse_origin/1:597": { + "line": 597, + "guard": null, + "pattern": "origin", + "kind": "defp", + "end_line": 606, + "ast_sha": "416f2269f24300d7a69076c23b10cfbcfba4ca041ca897f0ffaf5a9879a36d9f", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "856f9e7d6decfdd23c29af2e23e4f234ada402e3b5af5f23a5e69d379c742024", + "start_line": 597, + "name": "parse_origin", + "arity": 1 + }, + "check_origin_config/3:572": { + "line": 572, + "guard": null, + "pattern": "handler, endpoint, opts", + "kind": "defp", + "end_line": 593, + "ast_sha": "5b4e2777dbdcb7d894048b5aed3de7bad672c412c3f9bcc78f2fff5d641662cb", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "1db8bc7007747848232b3649a32aee48001b2410fd3096b4e0d824940123fdff", + "start_line": 572, + "name": "check_origin_config", + "arity": 3 + }, + "csrf_token_valid?/3:564": { + "line": 564, + "guard": null, + "pattern": "conn, session, csrf_token_key", + "kind": "defp", + "end_line": 568, + "ast_sha": "f9b3321f88a93ac67c0cdb5fca03436f060bcaa310a49c7ae171e154b801ee0b", + "source_file": "lib/phoenix/socket/transport.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", + "source_sha": "2e13cea734b0b26f6c9e36faa6e216dd1ff8aef2ae3a667e6139e008c806dc17", + "start_line": 564, + "name": "csrf_token_valid?", + "arity": 3 + } + }, + "Phoenix.Naming": { + "camelize/1:94": { + "line": 94, + "guard": null, + "pattern": "value", + "kind": "def", + "end_line": 94, + "ast_sha": "2c67ece3716533779f0149da8b92bb61a3ff663281e48d645eee71cb62d4e07f", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "dc78a1cbc8f34ee1ee7f2e5ac40e6dcc50f3f559c5063fdfc3a85df1354009c4", + "start_line": 94, + "name": "camelize", + "arity": 1 + }, + "camelize/2:101": { + "line": 101, + "guard": null, + "pattern": "<> = value, :lower", + "kind": "def", + "end_line": 103, + "ast_sha": "e10e1f124d509ef0c50f4f28d03db198c002ac259d9699af99d8b916cef7c5c6", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "1516909d957903ed67970deca4bb7780971580a195d017df558eac18dcc78b9c", + "start_line": 101, + "name": "camelize", + "arity": 2 + }, + "camelize/2:97": { + "line": 97, + "guard": null, + "pattern": "\"\", :lower", + "kind": "def", + "end_line": 97, + "ast_sha": "2ec4c7aec610386230d8b490381e49ec64d75f4825563d1e97ae832c5fd63af8", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "df244ad629d48a289344d51bd1244162e4e284ca186a8c5e853455147edce033", + "start_line": 97, + "name": "camelize", + "arity": 2 + }, + "camelize/2:98": { + "line": 98, + "guard": null, + "pattern": "<<95::integer, t::binary>>, :lower", + "kind": "def", + "end_line": 99, + "ast_sha": "4f63bc9e5817e55e6fa3f4d8782f96de67883fb4bd7eaff1e3fc6f9d2578b5eb", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "d2679a9651234101e6180842c047de38e559ea791ca737e53df4e545be37c42e", + "start_line": 98, + "name": "camelize", + "arity": 2 + }, + "humanize/1:120": { + "line": 120, + "guard": "is_atom(atom)", + "pattern": "atom", + "kind": "def", + "end_line": 121, + "ast_sha": "182de8b4cb2d826c22ed408988844c0a06d601bd747c27ebabad53ea7bea27a1", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "4aec0d487e52a042a46fa0b7d67a65780ad1df743ad18e27f891fca639ccff45", + "start_line": 120, + "name": "humanize", + "arity": 1 + }, + "humanize/1:122": { + "line": 122, + "guard": "is_binary(bin)", + "pattern": "bin", + "kind": "def", + "end_line": 130, + "ast_sha": "a1ad241b08faca2fe25140c7e9aa83242cd91191759108fb8c543f4e4daa92bd", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "4f1c48e5d706272b6364b184fd248de50eaaeb5a55cb669ae67ff2bce2802b18", + "start_line": 122, + "name": "humanize", + "arity": 1 + }, + "resource_name/1:19": { + "line": 19, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 19, + "ast_sha": "7ba94cbf74fd9d39aa9fe5db0ccdd419392af9907b9581646f3539cede68feba", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "1c1b421623ed779226b0e901b4ce7585e2855f389010e04d3e3ad6b5f3dd48ee", + "start_line": 19, + "name": "resource_name", + "arity": 1 + }, + "resource_name/2:19": { + "line": 19, + "guard": null, + "pattern": "alias, suffix", + "kind": "def", + "end_line": 25, + "ast_sha": "73e920149d7868c1d5de382022468cf8be731f5e286dfe3da20f7a7282878ee3", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "fe74c20a82790ff7a0a9a3be3eac8b70a2614ea4fda02997b1b54e4d9f4d69c8", + "start_line": 19, + "name": "resource_name", + "arity": 2 + }, + "to_lower_char/1:70": { + "line": 70, + "guard": "is_integer(char) and (char >= 65 and =<(char, 90))", + "pattern": "char", + "kind": "defp", + "end_line": 70, + "ast_sha": "996452a895e12e0cccc9eea1f3b301e0daaffc23f0fda342acdb7372e755b1b7", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "becafab6095ee9a45a665b8790370ab0d27b5ba5659b927c4a9bfd10ef915492", + "start_line": 70, + "name": "to_lower_char", + "arity": 1 + }, + "to_lower_char/1:71": { + "line": 71, + "guard": null, + "pattern": "char", + "kind": "defp", + "end_line": 71, + "ast_sha": "3989282711c9818c42279b7e9fc7c3b3a0f5f7b6021dd8c838e4cdd026d654af", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "b3c8dbce9298d8ef976a69d435bd06cea652d2423d5246e239ef2d4202db9d51", + "start_line": 71, + "name": "to_lower_char", + "arity": 1 + }, + "underscore/1:68": { + "line": 68, + "guard": null, + "pattern": "value", + "kind": "def", + "end_line": 68, + "ast_sha": "bd0aaf69044896c42ad2b5f0ecf97214dfad9a6da1ec935b80d65d87248fd7e2", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "c3f5d6a0ab8f8a34a2c5da36b2c81e4df91a298b2c1c0ab3c91ff7dce9493723", + "start_line": 68, + "name": "underscore", + "arity": 1 + }, + "unsuffix/2:41": { + "line": 41, + "guard": null, + "pattern": "value, suffix", + "kind": "def", + "end_line": 47, + "ast_sha": "e6eea8b052555b4dd3585508606412044d8add5de969e31e78f5ec35d05e120b", + "source_file": "lib/phoenix/naming.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", + "source_sha": "7908c11e270ff6df52f32bb5b3a7908d6c2a87bf61cfcc3c3e7dbaa6aedd92a2", + "start_line": 41, + "name": "unsuffix", + "arity": 2 + } + }, + "Phoenix.Flash": { + "get/2:16": { + "line": 16, + "guard": "is_atom(key) or is_binary(key)", + "pattern": "%mod{}, key", + "kind": "def", + "end_line": 22, + "ast_sha": "b0aeb44ea14cb6fffdfd0b54b6e4e77c157d84e2d63d2b1fee1d8ec9d7fdc92e", + "source_file": "lib/phoenix/flash.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/flash.ex", + "source_sha": "8c366e1fa2d3ab4ddca56bcfbecabae698cc0e33e15d0b45bab6f94d9372762b", + "start_line": 16, + "name": "get", + "arity": 2 + }, + "get/2:26": { + "line": 26, + "guard": "is_atom(key) or is_binary(key)", + "pattern": "%{} = flash, key", + "kind": "def", + "end_line": 27, + "ast_sha": "834ef518fb6551b5ede0268289f963c35c9f279a41c28636c3c418bd2c28de59", + "source_file": "lib/phoenix/flash.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/flash.ex", + "source_sha": "18da48c08c298e1ccc90a211e90b470e806175c7b2e22dc61068d2912bcbe19d", + "start_line": 26, + "name": "get", + "arity": 2 + } + }, + "Phoenix.Param": { + "__protocol__/1:1": { + "line": 1, + "guard": null, + "pattern": ":impls", + "kind": "def", + "end_line": 1, + "ast_sha": "4f1c606279ac67edd5528d121f2659b413d16a80d813d2f05a25033ac26c3f4d", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", + "start_line": 1, + "name": "__protocol__", + "arity": 1 + }, + "impl_for!/1:1": { + "line": 1, + "guard": null, + "pattern": "data", + "kind": "def", + "end_line": 1, + "ast_sha": "0129afca6d596b23db35947e4691e4dd75099b4c0c61622fd97605507956c79c", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", + "start_line": 1, + "name": "impl_for!", + "arity": 1 + }, + "impl_for/1:1": { + "line": 1, + "guard": null, + "pattern": "_", + "kind": "def", + "end_line": 1, + "ast_sha": "e6a47c766d4b1bfb12ea57a07a83017d7400497e63a53cc18e30992e2723fb3a", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", + "start_line": 1, + "name": "impl_for", + "arity": 1 + }, + "struct_impl_for/1:1": { + "line": 1, + "guard": null, + "pattern": "struct", + "kind": "defp", + "end_line": 1, + "ast_sha": "e241871f23063a938abbfb27c236c7ae3ad09bfb5054c8ce1d1f7b30ec66365e", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", + "start_line": 1, + "name": "struct_impl_for", + "arity": 1 + }, + "to_param/1:63": { + "line": 63, + "guard": null, + "pattern": "term", + "kind": "def", + "end_line": 63, + "ast_sha": "2598a950a2228266ac63b4e46ab6adb46472e140472ecb5cc3a8b31cd87d68d5", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "9ac9cf4a8c26dc07338a7c844baed12437ec3380cc7ed2a0115b428241c5c382", + "start_line": 63, + "name": "to_param", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen": { + "run/1:49": { + "line": 49, + "guard": null, + "pattern": "_args", + "kind": "def", + "end_line": 50, + "ast_sha": "09356baf05294a1be4d877b6c89c4f02a5d1133061e988d85973923b1d575371", + "source_file": "lib/mix/tasks/phx.gen.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.ex", + "source_sha": "c15bf928d21a70e41c36b29243761f967c77d12f5fc629a100e10f2d447e1b4c", + "start_line": 49, + "name": "run", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Embedded": { + "build/1:54": { + "line": 54, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 64, + "ast_sha": "ba1d55ebc6b3d9f623a463445f77e9c0a64ef0d09d680466ff3f2ff2e2ffc7be", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "958cab6226e45a37bba006b87db4de9f6653766d4b6651c0fd16a9ffc61da35b", + "start_line": 54, + "name": "build", + "arity": 1 + }, + "copy_new_files/3:105": { + "line": 105, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema, paths, binding", + "kind": "def", + "end_line": 109, + "ast_sha": "19af7128a56afb86e51066fa64063a4bb45e74b184499c239a9de9f0bafecb85", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "d278c70c9e5de696f9882f5c900a7b9054104b6213a65f85634004754ffd94e6", + "start_line": 105, + "name": "copy_new_files", + "arity": 3 + }, + "files_to_be_generated/1:100": { + "line": 100, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema", + "kind": "def", + "end_line": 101, + "ast_sha": "836c5e229c14c7b49397e5a11aae1bfaf230d374a132b88e9ec730210dff5a7d", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "edbb0e972769fbcc789fc74f8247631001db67234f2237cae70cf43d5387afd6", + "start_line": 100, + "name": "files_to_be_generated", + "arity": 1 + }, + "prompt_for_conflicts/1:93": { + "line": 93, + "guard": null, + "pattern": "schema", + "kind": "defp", + "end_line": 96, + "ast_sha": "f3ebba6f09507aaafdbfebf320f772d0f8a85751ac25e7bb4a01a2dadf970f7b", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "bee6f3131373fd7506ad81096775ca9a4d421535f9688f8619f6d4381712a0cd", + "start_line": 93, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "raise_with_help/1:81": { + "line": 81, + "guard": null, + "pattern": "msg", + "kind": "def", + "end_line": 83, + "ast_sha": "e64ca138101be4986f932fc66c2bec82da0a921cb180891af3c18c38dcd2e144", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "a09cec29e86945790f3d97ae21f6380d7295082ac65114a4fac62e0c84b662f0", + "start_line": 81, + "name": "raise_with_help", + "arity": 1 + }, + "run/1:39": { + "line": 39, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 50, + "ast_sha": "82d90884242784f4074e34dd2054497639a73fc86bfd59efddd1dd0763fc1869", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "c92192d1481ce8db7a46d9a0ba67cbc391fac4b1b94f90e3da7ba20cafab64d9", + "start_line": 39, + "name": "run", + "arity": 1 + }, + "validate_args!/1:68": { + "line": 68, + "guard": null, + "pattern": "[schema | _] = args", + "kind": "def", + "end_line": 72, + "ast_sha": "c22fd59fc81eedd53a90d926305e42635083cbe285e46499d85e1507baae347b", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "c895a6096eafa7e32142ff3a73cfacc6129343f10e8bc7b992e9d5dfdf2f437c", + "start_line": 68, + "name": "validate_args!", + "arity": 1 + }, + "validate_args!/1:75": { + "line": 75, + "guard": null, + "pattern": "_", + "kind": "def", + "end_line": 76, + "ast_sha": "ea8e3213d2e54dd0152e93e9d31ecdc162de6b86b60c8a0edae5839f7ef68933", + "source_file": "lib/mix/tasks/phx.gen.embedded.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", + "source_sha": "dada4dc83d81ccf2c8901374f7ac8482dcc8ed608e3f8f0dc5e5a64a3ac2a7b9", + "start_line": 75, + "name": "validate_args!", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Schema": { + "build/2:188": { + "line": 188, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 188, + "ast_sha": "4c476677119535391ce3657187afb1fc11a8ef238dc4096942743c366b3e25b6", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "059590d05ac4e593e27132e46d6d35958104ef18dad69b7a7c38281381137ed5", + "start_line": 188, + "name": "build", + "arity": 2 + }, + "build/3:188": { + "line": 188, + "guard": null, + "pattern": "args, parent_opts, help", + "kind": "def", + "end_line": 198, + "ast_sha": "c555515f5dd22ff5d98576a91000c8739a5e16a63d2f1370cbd97c127b7c42a9", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "f5b3f20d0e16d1877f0258536dc3689eb601b36958ed3d96755b52052373b05f", + "start_line": 188, + "name": "build", + "arity": 3 + }, + "copy_new_files/3:220": { + "line": 220, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{context_app: ctx_app, repo: repo, opts: opts} = schema, paths, binding", + "kind": "def", + "end_line": 245, + "ast_sha": "5d80d6ab9a58f5245a638641b98b42c0cf9ece6d4e77c03258da0618df84ec06", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "71086fd0922bb40cacc34c65a5423421372a4810a1911d6dd344242dff70a278", + "start_line": 220, + "name": "copy_new_files", + "arity": 3 + }, + "files_to_be_generated/1:215": { + "line": 215, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema", + "kind": "def", + "end_line": 216, + "ast_sha": "cfc61e405b012b62ae1290b7ddcb9b0b2fa2936c2d72b0f3ae756aeaa4ff22f1", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "941753b1e208bcafc57e1e93109eb3d693aa01345de09e4d229db4c482181788", + "start_line": 215, + "name": "files_to_be_generated", + "arity": 1 + }, + "maybe_update_repo_module/1:201": { + "line": 201, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 205, + "ast_sha": "ae1c709db1f407c414cef02a3bb6434c7d3ad8054c79e129b4cee036759fd727", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "526da3ca8ee524307dc95781a0af32a97f1121b1031116571ceb1a67f4514e33", + "start_line": 201, + "name": "maybe_update_repo_module", + "arity": 1 + }, + "pad/1:293": { + "line": 293, + "guard": "i < 10", + "pattern": "i", + "kind": "defp", + "end_line": 293, + "ast_sha": "8b589203e40ca35f83ec568fa85e008e7480f94a3d60e205b97c1343c4825ef2", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "73e7c06a9aa90212051bbd282f6e51e4e419e2e8968cea8ff13c37b5ae90a7de", + "start_line": 293, + "name": "pad", + "arity": 1 + }, + "pad/1:294": { + "line": 294, + "guard": null, + "pattern": "i", + "kind": "defp", + "end_line": 294, + "ast_sha": "7613e3e1bfe1c748170999bc1e64e19cbf322d289f35b52b80799f06fdcdf962", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "019ee63a3ac952acdb672c9b9c381889dbecd8c4fea6d62ffa991c27316520a9", + "start_line": 294, + "name": "pad", + "arity": 1 + }, + "print_shell_instructions/1:249": { + "line": 249, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema", + "kind": "def", + "end_line": 251, + "ast_sha": "e16cae37adb87df05c7040914693eb9b83ba4e59b6e4178a0b03d90acf2a1ecc", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "475717ced8a410a8647dd6aa6ce294bbacf9ab127073bd6c4116c9c44c51a5f8", + "start_line": 249, + "name": "print_shell_instructions", + "arity": 1 + }, + "prompt_for_conflicts/1:181": { + "line": 181, + "guard": null, + "pattern": "schema", + "kind": "defp", + "end_line": 184, + "ast_sha": "4ebed16af1090fd3b1fde82d10f0bbf870965463cb9125dcc7a9404cd5b56fcc", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "bee6f3131373fd7506ad81096775ca9a4d421535f9688f8619f6d4381712a0cd", + "start_line": 181, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "put_context_app/2:209": { + "line": 209, + "guard": null, + "pattern": "opts, nil", + "kind": "defp", + "end_line": 209, + "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", + "start_line": 209, + "name": "put_context_app", + "arity": 2 + }, + "put_context_app/2:210": { + "line": 210, + "guard": null, + "pattern": "opts, string", + "kind": "defp", + "end_line": 211, + "ast_sha": "97852ff283af0b58617a4a93d1e8a5d6859c264009a967a7b9a53e1bde5f434e", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", + "start_line": 210, + "name": "put_context_app", + "arity": 2 + }, + "raise_with_help/1:277": { + "line": 277, + "guard": null, + "pattern": "msg", + "kind": "def", + "end_line": 279, + "ast_sha": "df89099af45bf6da77884d80f6722f5fae62099f175bbacf21807a11f05ac2d4", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "a09cec29e86945790f3d97ae21f6380d7295082ac65114a4fac62e0c84b662f0", + "start_line": 277, + "name": "raise_with_help", + "arity": 1 + }, + "run/1:160": { + "line": 160, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 178, + "ast_sha": "35499c54af4ea0f7661dc243c49872adbafb0e4981e975acd2b48195c63ae3c8", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "87f110bdd959f277b81da4a1afc2e088156296a5ab44853f3cf0c49f6e9a5688", + "start_line": 160, + "name": "run", + "arity": 1 + }, + "timestamp/0:289": { + "line": 289, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 291, + "ast_sha": "3a10e0a2a76a5ce3100206ac91d09baa3d18d8c8895707311d5d55da99823cde", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "31815f67847bad4ae7aa82b79514b445b4ddd807b20356094669e72b46c33894", + "start_line": 289, + "name": "timestamp", + "arity": 0 + }, + "validate_args!/2:261": { + "line": 261, + "guard": null, + "pattern": "[schema, plural | _] = args, help", + "kind": "def", + "end_line": 268, + "ast_sha": "b8050d7b02dfcca9a813bcf300c9d29188f339b597e72418e1e91a54b5f656e1", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "9bba4cfc54ed93fb05eff613a8fcad46bed684c1172b01b54984e38c0ae67ea5", + "start_line": 261, + "name": "validate_args!", + "arity": 2 + }, + "validate_args!/2:271": { + "line": 271, + "guard": null, + "pattern": "_, help", + "kind": "def", + "end_line": 272, + "ast_sha": "e8e342b85119228478b2020aa721f7ca5c106a5731f706e99036f2f4db1e446a", + "source_file": "lib/mix/tasks/phx.gen.schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", + "source_sha": "3384137ada961cb108dfda84f5d6264762adfed431234cd8e9bffdf30b5c54f2", + "start_line": 271, + "name": "validate_args!", + "arity": 2 + } + }, + "Mix.Tasks.Phx.Digest": { + "run/1:58": { + "line": 58, + "guard": null, + "pattern": "all_args", + "kind": "def", + "end_line": 85, + "ast_sha": "b1009a0ce1ba7e8e15904d3da3e67f48dab1d6f4179ee1dfb061a55a528e5c54", + "source_file": "lib/mix/tasks/phx.digest.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.ex", + "source_sha": "3837a610c3f149cc2fbd4d826321ac926acefc84556d656d67a8305b80019dc1", + "start_line": 58, + "name": "run", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Html": { + "context_files/1:182": { + "line": 182, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: true} = context", + "kind": "defp", + "end_line": 183, + "ast_sha": "3f1f5773a352652e98659f95d64b39dea06e4606844dbae5bc76b31b3ac4cbc4", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", + "start_line": 182, + "name": "context_files", + "arity": 1 + }, + "context_files/1:186": { + "line": 186, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: false}", + "kind": "defp", + "end_line": 186, + "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", + "start_line": 186, + "name": "context_files", + "arity": 1 + }, + "copy_new_files/3:214": { + "line": 214, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", + "kind": "def", + "end_line": 218, + "ast_sha": "f33b6533a0580ef203ef23df185ac0e92de30ab96c5248eedc2320f959fe6f38", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "7849e380c3390159929d45e0fd3a4e91f293e7bdfbc8803742039da22a9b2539", + "start_line": 214, + "name": "copy_new_files", + "arity": 3 + }, + "default_options/1:318": { + "line": 318, + "guard": null, + "pattern": "{:array, :string}", + "kind": "defp", + "end_line": 319, + "ast_sha": "f58fab999b05901f2765f36488b54452e476ac6c67a344c0eaab8c8928b06a0b", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "f7baf8656ec69550ba797003cef4dbce49c50ef0b06cbbde34d1c7ec4a169d69", + "start_line": 318, + "name": "default_options", + "arity": 1 + }, + "default_options/1:321": { + "line": 321, + "guard": null, + "pattern": "{:array, :integer}", + "kind": "defp", + "end_line": 322, + "ast_sha": "fc71b3d0d379e7a4363968ae1542322b57144517a9a54f3590405eb6d3db3d7e", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "0c6bc5b7c2583cc53321531782442ea51cc59459c6217490af281d5912293cc3", + "start_line": 321, + "name": "default_options", + "arity": 1 + }, + "default_options/1:324": { + "line": 324, + "guard": null, + "pattern": "{:array, _}", + "kind": "defp", + "end_line": 324, + "ast_sha": "5d58293c50e5eb42c1fc4cac63844c442b64a79f7acb29119153166f52272db3", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "71475429cbe803cbdb6e7877819a8eb755b00b60d50eb7ad2408348c028d0ed0", + "start_line": 324, + "name": "default_options", + "arity": 1 + }, + "files_to_be_generated/1:191": { + "line": 191, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", + "kind": "def", + "end_line": 209, + "ast_sha": "8c2ab806806bba9b57ad0a95960e04a40f80750d31a4444840d574a09a3dab98", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "563f7bec5dbff34c327bd9faddedcdae3796cbed1fc66ef5daf4564c235af53c", + "start_line": 191, + "name": "files_to_be_generated", + "arity": 1 + }, + "indent_inputs/2:338": { + "line": 338, + "guard": null, + "pattern": "inputs, column_padding", + "kind": "def", + "end_line": 357, + "ast_sha": "4a53ac8e47d3856e849f74b12ce5bc0c18ce39612119ab8a91a55a371a581b1e", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "4bd69ad1b26ddea5eb3c2bdd20d1c87488ea5c485be2fef1a513549503b8fea8", + "start_line": 338, + "name": "indent_inputs", + "arity": 2 + }, + "inputs/1:260": { + "line": 260, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema", + "kind": "def", + "end_line": 314, + "ast_sha": "1c2a7874fcf2363701ff587ff80ebe36bf3571854c6d50f874f8262e23a7a47a", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "e108fa35154f63ec4892da9d8f780ca433a1695b9b9338cb70076effd0eebdb5", + "start_line": 260, + "name": "inputs", + "arity": 1 + }, + "label/1:326": { + "line": 326, + "guard": null, + "pattern": "key", + "kind": "defp", + "end_line": 326, + "ast_sha": "d44770f4330ec470ee629dbfa2f03dd77c005af0b2a0a8007b4aa09788b57e6d", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "a298472558e596e1e6ef15fbde1f3acc423119bdc3f18e26b72461c14e3fb8ac", + "start_line": 326, + "name": "label", + "arity": 1 + }, + "print_shell_instructions/1:222": { + "line": 222, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", + "kind": "def", + "end_line": 256, + "ast_sha": "b7b0efec8eeac0019a67f43b8ea8106b96eb968b6b88444b862e55a53133de0e", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "a194e9344c78f1e05c312348a35f2b5b8ae8eb632c2035352d1f2a03eed6dcda", + "start_line": 222, + "name": "print_shell_instructions", + "arity": 1 + }, + "prompt_for_conflicts/1:175": { + "line": 175, + "guard": null, + "pattern": "context", + "kind": "defp", + "end_line": 179, + "ast_sha": "817f32e3f8e5f8587beaebb8d0fd678ebd42bebbab256e0c7eafd67ddd3d1a5d", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "90bb78b802f638a452de361d55b4ad7f730fbc458b81fbed27efc49236a0c1d1", + "start_line": 175, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "run/1:121": { + "line": 121, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 172, + "ast_sha": "38184ce305cf79906745d52979f4f1ca8a3b12de614be9299f22a2abe8e85557", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "808ab010e65c1112e2bab808c9c3d963a1acbd0c01f8007efead8367b6476786", + "start_line": 121, + "name": "run", + "arity": 1 + }, + "scope_assign_route_prefix/1:328": { + "line": 328, + "guard": "not (route_prefix == nil)", + "pattern": "%{scope: %{route_prefix: route_prefix, assign_key: assign_key}} = schema", + "kind": "defp", + "end_line": 332, + "ast_sha": "48ed39cfa0e90789389256cca1c0047a9055b9d735811ef29f42295b1ae1ffba", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "247e983a0169c88f62cf9b99c16687f4771d0a3659a130b699eb8f10bd06326e", + "start_line": 328, + "name": "scope_assign_route_prefix", + "arity": 1 + }, + "scope_assign_route_prefix/1:335": { + "line": 335, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 335, + "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", + "source_file": "lib/mix/tasks/phx.gen.html.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", + "source_sha": "e9a8e972479e20da74d9b8d9fdd7cc2007152cc11ee0fa7b7a4a1cc6cfadb0e4", + "start_line": 335, + "name": "scope_assign_route_prefix", + "arity": 1 + } + }, + "Phoenix.Param.Integer": { + "__impl__/1:66": { + "line": 66, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 66, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "b045dc19c4eaaae208f712a98cb2e5b0c97805619f103ab499ace1bffb01394e", + "start_line": 66, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:67": { + "line": 67, + "guard": null, + "pattern": "int", + "kind": "def", + "end_line": 67, + "ast_sha": "7a9ee61c9acab3d0d252dbf4c1efbb76ef4a070d8a469f687147b435df4f7db5", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "5189fe06905ea550f6dedd6c94222706855a297c098354b920391fc9b589d978", + "start_line": 67, + "name": "to_param", + "arity": 1 + } + }, + "Phoenix.Endpoint": { + "__before_compile__/1:644": { + "line": 644, + "guard": null, + "pattern": "%{module: module}", + "kind": "defmacro", + "end_line": 697, + "ast_sha": "e3a467474470cf6b86f9572c8c375e14fd715adc3cc284446689097c3e515afe", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "b8c4375a53ad3ea9c4b3174d36772942cd63bc1a44b87c0202a988e574ffa57d", + "start_line": 644, + "name": "__before_compile__", + "arity": 1 + }, + "__force_ssl__/2:637": { + "line": 637, + "guard": null, + "pattern": "module, force_ssl", + "kind": "def", + "end_line": 639, + "ast_sha": "f63e4831bd8d9fce961485e3f67a27d70df29479a52ce849821a707293671bdb", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "6236598fede8287c726928ab67de40a9d7239465cd177f9f13ce76d46583e6a0", + "start_line": 637, + "name": "__force_ssl__", + "arity": 2 + }, + "__using__/1:408": { + "line": 408, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 415, + "ast_sha": "ce9fe0e02e86d0c12c749555ff209b988c3a3a8b4129b21c25309e6da7c250bc", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "453282522d21280ff85cc31c883495cef87e769c227b60b862632f5292196bb0", + "start_line": 408, + "name": "__using__", + "arity": 1 + }, + "config/1:419": { + "line": 419, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 421, + "ast_sha": "75a3f312d3642b2b9a6470c3fb2bf46e51534bff132ee3a756e2f767a412b2e6", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "31a176555d882635c20fc83b27f86c6426897983ae36fac6d4db31c933523971", + "start_line": 419, + "name": "config", + "arity": 1 + }, + "instrument/4:1075": { + "line": 1075, + "guard": null, + "pattern": "_endpoint_or_conn_or_socket, _event, _runtime, _fun", + "kind": "defmacro", + "end_line": 1075, + "ast_sha": "0d33445e602fa0b6b4717c35afae371ddfa3ca7f15260aafe9904dfc51c90d42", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "d80627a04617360c9015155d479bcc2e5257cd641ad49214e28bdd699b23b531", + "start_line": 1075, + "name": "instrument", + "arity": 4 + }, + "maybe_validate_keys/2:801": { + "line": 801, + "guard": "is_list(opts)", + "pattern": "opts, keys", + "kind": "defp", + "end_line": 801, + "ast_sha": "e9da1c0481e39274ce847afd2fdf0944f8469519a10d36bc1fa26493eb77dc15", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "b515929ca479fd14d6db68d11b7751f0ff30fa765927104a8edd90684f94931d", + "start_line": 801, + "name": "maybe_validate_keys", + "arity": 2 + }, + "maybe_validate_keys/2:802": { + "line": 802, + "guard": null, + "pattern": "other, _", + "kind": "defp", + "end_line": 802, + "ast_sha": "7dd091a67e628cc9910ccc7e4b138f2e50011099b7214705998b71748c31f110", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "acef49f9f49f5e93751f9ded9c3fd21ae41692b5cca78ced24ee76ac81c86c6f", + "start_line": 802, + "name": "maybe_validate_keys", + "arity": 2 + }, + "plug/0:478": { + "line": 478, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 478, + "ast_sha": "c3a944fbb3742a0201573751bdc647cbc58e28982621a129a0f85606cb237db7", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "dc24171ffc4655cc8a629a6b9f8b9cb14458eff5d73b38616f30ad2ddcf5b60b", + "start_line": 478, + "name": "plug", + "arity": 0 + }, + "pubsub/0:437": { + "line": 437, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 437, + "ast_sha": "e09c8fee249109809da2afa2ff8d3e86b95f6616524d4e7c47ad7a96191733fd", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "c3929478502c3abcf190a2240af55ee4813897ca766c88ce327b81da3f42ee86", + "start_line": 437, + "name": "pubsub", + "arity": 0 + }, + "put_auth_token/2:769": { + "line": 769, + "guard": null, + "pattern": "true, enabled", + "kind": "defp", + "end_line": 769, + "ast_sha": "953938441f9bea9f7c4abd295549faad8562cb1ccce3f785f5b7abef4d1c2787", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "075fd79ca764005e240d2f4547fc92cc006b4ab0b7fb2225e3418d034e2aa31d", + "start_line": 769, + "name": "put_auth_token", + "arity": 2 + }, + "put_auth_token/2:770": { + "line": 770, + "guard": null, + "pattern": "opts, enabled", + "kind": "defp", + "end_line": 770, + "ast_sha": "57b73d8fa0e55a8afb57a475fdc80bc6d0fd5fb9029b5e1b201e2277462ff9d1", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "26ecc1a2c7d1629e2e37fff5318c724b2f575371c8ecb36bd1447f7b9ffe1b85", + "start_line": 770, + "name": "put_auth_token", + "arity": 2 + }, + "server/0:513": { + "line": 513, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 513, + "ast_sha": "94d73bb89c0e11a7d63cf7e5997106ef3a5449fed0e7401d8eaa48afcb0de11e", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "dac259ad275df9144dbd69283855babc5847d3aabbdeaab20c9c5e5914d92e02", + "start_line": 513, + "name": "server", + "arity": 0 + }, + "server?/2:1091": { + "line": 1091, + "guard": "is_atom(otp_app) and is_atom(endpoint)", + "pattern": "otp_app, endpoint", + "kind": "def", + "end_line": 1092, + "ast_sha": "f5ff70268c7e6b6745a8e99929f5884aefd0fdfaf258196de28437bcc4997a81", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "08d442db71d051520b1d1762e1a7b260b3effb1ed2b49ceed719cfb4b3523b02", + "start_line": 1091, + "name": "server?", + "arity": 2 + }, + "socket/2:1065": { + "line": 1065, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 1065, + "ast_sha": "33170dea01f5958d1d85fb840554f73378343e2cfea52bb3d741f884e15e1c95", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "c8d529278b8239feef16e03ca4bb624053266cd929447db4bfb6caefc788a6e6", + "start_line": 1065, + "name": "socket", + "arity": 2 + }, + "socket/3:1065": { + "line": 1065, + "guard": null, + "pattern": "path, module, opts", + "kind": "defmacro", + "end_line": 1069, + "ast_sha": "91f10db91f04214d7d3a31ff8a8d6b650e959579720da4538c589adab38b3e0f", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "28b86f769a41ac97f6cc1a0bd45f9e0c73b096604da5870d17aaa5b8c2398c51", + "start_line": 1065, + "name": "socket", + "arity": 3 + }, + "socket_path/2:772": { + "line": 772, + "guard": null, + "pattern": "path, config", + "kind": "defp", + "end_line": 798, + "ast_sha": "2eb3da613600cfb78c852f3cdec94abbb0a401adce3573704b5e3431a415733a", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "3fc2aa07db99720626350fbdc6a610935bede22c24f3d551271f45ea17237a09", + "start_line": 772, + "name": "socket_path", + "arity": 2 + }, + "socket_paths/4:702": { + "line": 702, + "guard": null, + "pattern": "endpoint, path, socket, opts", + "kind": "defp", + "end_line": 766, + "ast_sha": "8284953e0d90242d88679f310ee8ec836646be85fbbd4459f2eb6462f37c209d", + "source_file": "lib/phoenix/endpoint.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", + "source_sha": "88647afc72e344875d4d7885ed8cf78d07923a84f822bdc6010b6c31c3946c78", + "start_line": 702, + "name": "socket_paths", + "arity": 4 + } + }, + "Phoenix.CodeReloader.Server": { + "with_build_lock/1:450": { + "line": 450, + "guard": null, + "pattern": "fun", + "kind": "defp", + "end_line": 450, + "ast_sha": "ba1934804ce69336c0fd10e5bdf9aa9dfebb0d4c9d6b9bc4df575e5db3eced33", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "eb927730aa7f9621cfa53ed22a9fe0d05a64da410b3cabf1a3c883845060652e", + "start_line": 450, + "name": "with_build_lock", + "arity": 1 + }, + "read_backup/1:166": { + "line": 166, + "guard": "is_list(path)", + "pattern": "path", + "kind": "defp", + "end_line": 169, + "ast_sha": "ec2f0bbeaae03c81d102fe7b0bd4ca43feca33068efd84d8fd06fad3ebe7b2e0", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "2d5f799e120d0472403c1a4d268854f57de4d1ce8ff5f42cbc02f10b62b05442", + "start_line": 166, + "name": "read_backup", + "arity": 1 + }, + "write_backup/1:175": { + "line": 175, + "guard": null, + "pattern": "{:ok, path, file}", + "kind": "defp", + "end_line": 175, + "ast_sha": "5e4086636677bf1b82f9391004a8fe63362a47341f5113806ebc3fcb7569f5f4", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "5c3c7ec71d21052d7ce1c7fb21f7c787582c1cd45503268583625c48740b1bc7", + "start_line": 175, + "name": "write_backup", + "arity": 1 + }, + "sync/0:20": { + "line": 20, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 27, + "ast_sha": "a15adb8a221aabb4370126f8822a294e35aed689efafe7c2f208e7f9b0a4b2d0", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "14bfc5edb3ceed24a0ca70357cc08c53fa787b38b362c064bbd914c5c2185d6b", + "start_line": 20, + "name": "sync", + "arity": 0 + }, + "code_change/3:3": { + "line": 3, + "guard": null, + "pattern": "_old, state, _extra", + "kind": "def", + "end_line": 940, + "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "31983bfe8f79d86d314c55191170a0aaaca469968542b28c2b77e1d81dfe5530", + "start_line": 3, + "name": "code_change", + "arity": 3 + }, + "write_backup/1:176": { + "line": 176, + "guard": null, + "pattern": ":error", + "kind": "defp", + "end_line": 176, + "ast_sha": "ca2882601aaf6264708cae6d31e62c5863e9c2588a695e472b8a1a019c49e31d", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "ff0945a83def68aef03b9add8a7aecb47797229a84b72e0c5223d75413bf4644", + "start_line": 176, + "name": "write_backup", + "arity": 1 + }, + "terminate/2:3": { + "line": 3, + "guard": null, + "pattern": "_reason, _state", + "kind": "def", + "end_line": 3, + "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", + "start_line": 3, + "name": "terminate", + "arity": 2 + }, + "handle_call/3:37": { + "line": 37, + "guard": null, + "pattern": ":check_symlinks, _from, state", + "kind": "def", + "end_line": 59, + "ast_sha": "15e1c1133e3268df092df786ef3b08fc68838cd0ab75a6a55d305ea8e07821e3", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "38b6b73d7a1951437b3308a3936b5da16bce5f2e2a487f62288eaf05839e8087", + "start_line": 37, + "name": "handle_call", + "arity": 3 + }, + "can_symlink?/0:142": { + "line": 142, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 155, + "ast_sha": "f72e553f948b7c47ea89433b6596f8f43dd1122e2264e6b69817f6dfa728bf2e", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "e80929b2eaf8a186580731b98d7bf9a507dfa72921d59dcdd3f9a532a2c91533", + "start_line": 142, + "name": "can_symlink?", + "arity": 0 + }, + "run_compilers/4:399": { + "line": 399, + "guard": null, + "pattern": "[compiler | rest], args, status, diagnostics", + "kind": "defp", + "end_line": 406, + "ast_sha": "ec0fed79d2a115fdf5858e8967b26dd46128373a9bfb787379bb59c9e11fbcc9", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "451fbb47fae0c15c04355617c66f827398ea11d72420fa87ebe094c5b19b50b8", + "start_line": 399, + "name": "run_compilers", + "arity": 4 + }, + "warn_missing_mix_listener/0:187": { + "line": 187, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 189, + "ast_sha": "52d4e1bf22d7519b91225310cb8809d47a020302d2d5d69f5299f5a47bfe415b", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "8d574117dee40a21c816333b917b7fb584769f1e62aa7448facaf8ebd2ce92bf", + "start_line": 187, + "name": "warn_missing_mix_listener", + "arity": 0 + }, + "handle_cast/2:116": { + "line": 116, + "guard": null, + "pattern": "{:sync, pid, ref}, state", + "kind": "def", + "end_line": 118, + "ast_sha": "ee46c73737dd3aadb3e68f5857bef8db2ae333f87896c59222cfd173b19c1148", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "6542e194de158fa14aa613610a007de4b8c3af426fdec3278daaa4041977f1db", + "start_line": 116, + "name": "handle_cast", + "arity": 2 + }, + "mix_compile/6:210": { + "line": 210, + "guard": null, + "pattern": "{:module, Mix.Task}, compilers, apps_to_reload, compile_args, timestamp, purge_fallback?", + "kind": "defp", + "end_line": 246, + "ast_sha": "8ff574b065cbb3fca28ffc1609f9d30214f8f988f7085a053c42e9e0cea2a33c", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "9e8e48b09850eb2c2ff699002db483560ac327e1294015706faa1c5086372e34", + "start_line": 210, + "name": "mix_compile", + "arity": 6 + }, + "default_reloadable_apps/0:125": { + "line": 125, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 129, + "ast_sha": "6acc2341b95dcf4d903aab6595c80bde921b0a900c0bf74ff91613ca5b559fb7", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "ba8f90d7566a27361c49bc051fafedd0fa03f30543f97b555ddd5e5f4dc9f1be", + "start_line": 125, + "name": "default_reloadable_apps", + "arity": 0 + }, + "mix_compile_project/7:275": { + "line": 275, + "guard": null, + "pattern": "nil, _, _, _, _, _, _", + "kind": "defp", + "end_line": 275, + "ast_sha": "535bcfa8d648d52576e28667e7cc614f54068a05a33b3369c63fc783750ce1ac", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "1a7554268c5cf0d2c195f54d107ca2eb3710c2f43928bd6f52d67ebd0ba98560", + "start_line": 275, + "name": "mix_compile_project", + "arity": 7 + }, + "os_symlink/1:133": { + "line": 133, + "guard": null, + "pattern": "{:win32, _}", + "kind": "defp", + "end_line": 135, + "ast_sha": "93a93ed2d5f9eea01b205423fac2663fe82ac1e41de85350bcb8f5708071bdf0", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "b3a11dc74cb852b2e0bd0e37ac69db5292816e990d1e51d716bbb3b0fb527d83", + "start_line": 133, + "name": "os_symlink", + "arity": 1 + }, + "timestamp/0:360": { + "line": 360, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 360, + "ast_sha": "a06bc1128086e8392553788ebf17b68be4f4201c55815eb6668d59773d61becf", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "cee8e1c0678d0fb65f701112ebb0e5dc1b047b482c5ff6f5443a5a8a0157122f", + "start_line": 360, + "name": "timestamp", + "arity": 0 + }, + "with_logger_app/2:436": { + "line": 436, + "guard": null, + "pattern": "config, fun", + "kind": "defp", + "end_line": 444, + "ast_sha": "0aa47c7983543c50c03b135680542c027d53a220223a0b8792904b0f2d07466e", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "0587688d691554a7387808399b24a70c90ce04997421b34d3210d62848f8bd32", + "start_line": 436, + "name": "with_logger_app", + "arity": 2 + }, + "start_link/1:8": { + "line": 8, + "guard": null, + "pattern": "_", + "kind": "def", + "end_line": 9, + "ast_sha": "3ef624f4455e0a50950ad3edad2e84ceabb9976067d02c4c1882836abc8c1944", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "e1805dbddf7119242335e990fb2177b71999801ab3b0ff099b0c41cfb3b09312", + "start_line": 8, + "name": "start_link", + "arity": 1 + }, + "os_symlink/1:139": { + "line": 139, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 139, + "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "e0f93d19891fcf43e713b0d30e9dddfd765860ab8cf9f660de4f1b677a509e7a", + "start_line": 139, + "name": "os_symlink", + "arity": 1 + }, + "run_compiler/2:410": { + "line": 410, + "guard": null, + "pattern": "compiler, args", + "kind": "defp", + "end_line": 412, + "ast_sha": "d4b465d77e95c80195ed33f456c103b827a786dd11d338c8d38e2123313fd77e", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "ed0ec730dbe4cd6052db37bea3ae7419db0a0bcb022d547ba51e7c5e9540e02a", + "start_line": 410, + "name": "run_compiler", + "arity": 2 + }, + "load_backup/1:160": { + "line": 160, + "guard": null, + "pattern": "mod", + "kind": "defp", + "end_line": 163, + "ast_sha": "8df57cdd323ed99fea00849309fad47d5bae8f507f1aab648e10db588432479f", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "f3e5ee6278e046754994def27f3b189dfbf34b0f652f326ff30862d1acf655aa", + "start_line": 160, + "name": "load_backup", + "arity": 1 + }, + "normalize/2:415": { + "line": 415, + "guard": null, + "pattern": "result, name", + "kind": "defp", + "end_line": 428, + "ast_sha": "ac43def6fb9fbfc61c481a67aec3e1c7768b6e7b68c24d1b3784055b30ff65b3", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "0af3f3a1bb18d99b530ae7be9b4edf2e60ed0c036b130bff016440b3fb6f9880", + "start_line": 415, + "name": "normalize", + "arity": 2 + }, + "read_backup/1:173": { + "line": 173, + "guard": null, + "pattern": "_path", + "kind": "defp", + "end_line": 173, + "ast_sha": "9244a6e9b085ea0c1b33db6c78c0aac4d75e2a6adc0314a5e0b49f675c302026", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "6768602160487ac0d8d8ae010826a26f9fe5063c75973272ee04e93e4d3bdc2a", + "start_line": 173, + "name": "read_backup", + "arity": 1 + }, + "purge_modules/1:362": { + "line": 362, + "guard": null, + "pattern": "path", + "kind": "defp", + "end_line": 367, + "ast_sha": "532085bc342961909af1c78d3f9a7157d47124ae275e00c433395003fb2a18cb", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "06fd4304d24dd8fcbdac8f600f0a08161ef3ae63e300b0faa2b078b00bea9040", + "start_line": 362, + "name": "purge_modules", + "arity": 1 + }, + "mix_compile_project/7:277": { + "line": 277, + "guard": null, + "pattern": "app, apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", + "kind": "defp", + "end_line": 287, + "ast_sha": "2a70d08056430ae842bf36a05c03e96660e025e474f1d3b34c33cca44121b77c", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "5dbd281a579a2001312264b340413b6298d219b9a485dc5a45bea1ea5b8531c9", + "start_line": 277, + "name": "mix_compile_project", + "arity": 7 + }, + "mix_compile/4:320": { + "line": 320, + "guard": null, + "pattern": "compilers, compile_args, config, consolidation_path", + "kind": "defp", + "end_line": 355, + "ast_sha": "47688cbcdf52c3ca334bd36ae88111eff3f5e74486d060fd79703015aa260137", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "f73c3c98356e4402bb261bc5b6382b6e0a58d490da2fd5d29927e2476dab7345", + "start_line": 320, + "name": "mix_compile", + "arity": 4 + }, + "handle_call/3:62": { + "line": 62, + "guard": null, + "pattern": "{:reload!, endpoint, opts}, from, state", + "kind": "def", + "end_line": 113, + "ast_sha": "1ae01eaa78982fa60a9c95a786ce9086bb4d1b3891fce5638be0ec386a949eda", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "4e331f44ab17a5201f6e29a959984ff50c21964224ebdb510292ad5596ab213a", + "start_line": 62, + "name": "handle_call", + "arity": 3 + }, + "all_waiting/2:178": { + "line": 178, + "guard": null, + "pattern": "acc, endpoint", + "kind": "defp", + "end_line": 182, + "ast_sha": "ad316be342055c1328e21b638d5698056b4b702bb6be745f6f3ea6d196abc990", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "a2faab03c700827619911067b1441a5a6d8a2be2d1472f62318386e23aebee19", + "start_line": 178, + "name": "all_waiting", + "arity": 2 + }, + "check_symlinks/0:12": { + "line": 12, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 13, + "ast_sha": "4e8e2d287c098206922d307e56ce6228b702a1fb27ab57bc5df08621fca333a9", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "1029664bd0a91d06588ff83289349aaa1eac7df484d56a05a574bebc980ca1aa", + "start_line": 12, + "name": "check_symlinks", + "arity": 0 + }, + "purge_module/1:375": { + "line": 375, + "guard": null, + "pattern": "module", + "kind": "defp", + "end_line": 377, + "ast_sha": "a56a711f5834de552daa80562ee56c9b4eacede93d309d6bc9225beda8e9b7e6", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "b1d7fd3685baa44e4d541b2b3874fc347384c1efc6b53748611ca09a0b9af542", + "start_line": 375, + "name": "purge_module", + "arity": 1 + }, + "reload!/2:16": { + "line": 16, + "guard": null, + "pattern": "endpoint, opts", + "kind": "def", + "end_line": 17, + "ast_sha": "f4430b426f202a3eee7479055c2ec5ba0211b4ffc9fdfa90609bdfabb85e6c8c", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "b27e7b7bf39178feef7a2f3d9791e104405888197f3ecc1c88b9285d4fd95e34", + "start_line": 16, + "name": "reload!", + "arity": 2 + }, + "mix_compile_deps/7:259": { + "line": 259, + "guard": null, + "pattern": "deps, apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", + "kind": "defp", + "end_line": 270, + "ast_sha": "5627b4ba528b53378a8766cbfc06edb1c924d2a1c6d3949707ed176bafb6bae8", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "2da98b17ea778f8d273ab5b3cf76e4f95ffacf4519282e5e2d33d528ae7a46d8", + "start_line": 259, + "name": "mix_compile_deps", + "arity": 7 + }, + "run_compilers/4:395": { + "line": 395, + "guard": null, + "pattern": "[], _, status, diagnostics", + "kind": "defp", + "end_line": 396, + "ast_sha": "d17b5692e701a33da0cd376674ce0f66134bed7638ffaf32e74f71908579ee07", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "116bec3dbd89e6dde80e47efbc7d8450aac0f1bf8e2540f86bd6559ab1e5923e", + "start_line": 395, + "name": "run_compilers", + "arity": 4 + }, + "mix_compile_unless_stale_config/5:291": { + "line": 291, + "guard": null, + "pattern": "compilers, compile_args, timestamp, path, purge_fallback?", + "kind": "defp", + "end_line": 314, + "ast_sha": "c4debce35d8e2db30e2b891b93f76591c8a1a8c0b18944b565aee5f04d364b9f", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "177ee325aaac3831458ec0aeaf50e48abf921fa6fca6206c446c92fd71933319", + "start_line": 291, + "name": "mix_compile_unless_stale_config", + "arity": 5 + }, + "proxy_io/1:380": { + "line": 380, + "guard": null, + "pattern": "fun", + "kind": "defp", + "end_line": 389, + "ast_sha": "6e4c61d858d55a563868514189b029fa8270cab29802302a535b75193baf2ef1", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "b4df16d2080ad61a510dd45a574eb3eef67efd719355e291c6fbe713ed1687f0", + "start_line": 380, + "name": "proxy_io", + "arity": 1 + }, + "handle_info/2:121": { + "line": 121, + "guard": null, + "pattern": "_, state", + "kind": "def", + "end_line": 122, + "ast_sha": "65ac04f4317532edd4f4e759760b6fbe89093befc57712e1d00884f951bc0c34", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "bde504cfc1bc8be6dcf1880e72de7ff231260cfd36d88c2577f8f24004e5ea9e", + "start_line": 121, + "name": "handle_info", + "arity": 2 + }, + "mix_compile/6:252": { + "line": 252, + "guard": null, + "pattern": "{:error, _reason}, _, _, _, _, _", + "kind": "defp", + "end_line": 253, + "ast_sha": "43d9095841359b34c72beda65f796f871e203371a73125d270d26d804537f1b3", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "16b70d15b2b291e84f471b27310d2e0fa65834ad6e8c589993d162d50fd71057", + "start_line": 252, + "name": "mix_compile", + "arity": 6 + }, + "init/1:33": { + "line": 33, + "guard": null, + "pattern": ":ok", + "kind": "def", + "end_line": 34, + "ast_sha": "334fa76dc0c033348e14225fe6221747e36f73ef41bb2efb980855eddfdc9b50", + "source_file": "lib/phoenix/code_reloader/server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", + "source_sha": "ca9a986e602b40a2e6f13864bf2cf77d4f679240be55502ed5ee7f371636d312", + "start_line": 33, + "name": "init", + "arity": 1 + } + }, + "Mix.Phoenix.Scope": { + "__struct__/0:4": { + "line": 4, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 4, + "ast_sha": "333df4d514c402ff675e1ac0953e447fb385a63b5b094ac7dfec25f447dbfc52", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "f6d2eee0beb9d35dccee762f886c09483fa4253d7c4c417e6923dd6b281e220d", + "start_line": 4, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:4": { + "line": 4, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 4, + "ast_sha": "2a7f50ee20d17b75bc46ce36270ee689bec7cb840de905fdee56a52f5d934e3a", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "f6d2eee0beb9d35dccee762f886c09483fa4253d7c4c417e6923dd6b281e220d", + "start_line": 4, + "name": "__struct__", + "arity": 1 + }, + "default_scope/1:53": { + "line": 53, + "guard": null, + "pattern": "otp_app", + "kind": "def", + "end_line": 65, + "ast_sha": "646ab727e73497341bbb171de80d20bae4119b464ee1c93938060c9cc732ce05", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "0fafe5ed6ae6517da008831540cbc0b7d557f5c6a150182d6484d1f57ebf6272", + "start_line": 53, + "name": "default_scope", + "arity": 1 + }, + "new!/2:22": { + "line": 22, + "guard": null, + "pattern": "name, opts", + "kind": "def", + "end_line": 37, + "ast_sha": "9a31dd1661e10c7623f7d05d4336fa92d74426303f83c158912f8c6d15d6f7dd", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "c3f2942bdd3d3cde894f51af90e9a1ac153e2902004c0e158d22bbf36591d6f8", + "start_line": 22, + "name": "new!", + "arity": 2 + }, + "route_prefix/2:122": { + "line": 122, + "guard": "not (route_prefix == nil)", + "pattern": "scope_key, %{scope: %{route_prefix: route_prefix, route_access_path: route_access_path}} = _schema", + "kind": "def", + "end_line": 150, + "ast_sha": "2fadadf7e4e306c6d58b5f9c48094bcd60cb5b232b965a5df7574f9842978fe4", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "563bd70dff29dbc9cb9402280433e3b934033ac484eafc2647ee1bc97cdb6f64", + "start_line": 122, + "name": "route_prefix", + "arity": 2 + }, + "route_prefix/2:153": { + "line": 153, + "guard": null, + "pattern": "_scope_key, _schema", + "kind": "def", + "end_line": 153, + "ast_sha": "97d09b79b94aa2206d7a4fa04f432a57056385128e847c42ad957c9e4a12b898", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "a2ce46307479dabef96304e6e59e1602031cc87a66e836dd02bf6238eb177073", + "start_line": 153, + "name": "route_prefix", + "arity": 2 + }, + "scope_from_opts/3:75": { + "line": 75, + "guard": "is_binary(bin)", + "pattern": "_otp_app, bin, false", + "kind": "def", + "end_line": 76, + "ast_sha": "24416ce6bc694d5bbd319ff3accab74dfbc2df4f72281bd7a0f15ddc5c0b3d0a", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "7b7d37c52e8f98825bfcd9a646d42c6c2ec533d99505410de66d2c00cbedc52f", + "start_line": 75, + "name": "scope_from_opts", + "arity": 3 + }, + "scope_from_opts/3:79": { + "line": 79, + "guard": null, + "pattern": "_otp_app, _name, true", + "kind": "def", + "end_line": 79, + "ast_sha": "c8085f2fdaccbd674d288ef6a6fc851aa2f1325a92e605ec29ace625bc7d0ede", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "19368de6c24bda4d66afdc5011dc52c854b740de090f2f24551018740803c844", + "start_line": 79, + "name": "scope_from_opts", + "arity": 3 + }, + "scope_from_opts/3:81": { + "line": 81, + "guard": null, + "pattern": "otp_app, nil, _", + "kind": "def", + "end_line": 81, + "ast_sha": "01563c97b0661419a5ff6ba401774128a0467adc4e8c3b76d5b3445ea5bb6056", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "fcb5aaa77eade1d253caa3740e89e22897d05989329fa05a2ad1962f24f8d439", + "start_line": 81, + "name": "scope_from_opts", + "arity": 3 + }, + "scope_from_opts/3:83": { + "line": 83, + "guard": null, + "pattern": "otp_app, name, _", + "kind": "def", + "end_line": 94, + "ast_sha": "518fbddaf3b064fff6c7f3dc32afb354f442fac5146ee631e8d7ac91c3b0675c", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "b0bae185aebea0a3d871b6000c28df7dce260fee1cc4be7f0f9c0ffcaab2539e", + "start_line": 83, + "name": "scope_from_opts", + "arity": 3 + }, + "scopes_from_config/1:44": { + "line": 44, + "guard": null, + "pattern": "otp_app", + "kind": "def", + "end_line": 47, + "ast_sha": "53a5dcde9c4ae33ff713e49d8dd9cdd55e2127776df28371e6bb565d56834509", + "source_file": "lib/mix/phoenix/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", + "source_sha": "64ef553c825764806b72942bfdac81aa94db29855bb88dac2f2da80d678e3788", + "start_line": 44, + "name": "scopes_from_config", + "arity": 1 + } + }, + "Phoenix.Param.Atom": { + "__impl__/1:78": { + "line": 78, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 78, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "de2003188243d5858057dba638c8139359d7f6807b59fe1b6f10a42a9cd1c0da", + "start_line": 78, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:79": { + "line": 79, + "guard": null, + "pattern": "nil", + "kind": "def", + "end_line": 80, + "ast_sha": "656c1525e53d3fe0bab71fc5c6c5a81f28870417c4dd45d9938bbf2e33ec591e", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "5adea25f1d81bedb826dee0bbb543588d07138fe9e530b14d2985db17277c8c4", + "start_line": 79, + "name": "to_param", + "arity": 1 + }, + "to_param/1:83": { + "line": 83, + "guard": null, + "pattern": "atom", + "kind": "def", + "end_line": 84, + "ast_sha": "45903349c732f172e12d423567d29750e0a94b3349a9f224604d38ac862f087e", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "aa7b4b710ab4655cb4c4c042f0c2cbcdef47dc4a74b0f52ff2e5169513b44b02", + "start_line": 83, + "name": "to_param", + "arity": 1 + } + }, + "Phoenix.Param.Map": { + "__impl__/1:88": { + "line": 88, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 88, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "24ec10101eec006b1ad959e9447d89705819d5207d89b4b708eec4aaa5cb42cd", + "start_line": 88, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:89": { + "line": 89, + "guard": null, + "pattern": "map", + "kind": "def", + "end_line": 91, + "ast_sha": "626fcf7967578b8a0da4214fa93950a286decbf9e9726becd709b52ad540fe5f", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "f0601ac2aee88f1b14135f9c0190f2e5ede449cd3a75808d93e163a10dbb48f8", + "start_line": 89, + "name": "to_param", + "arity": 1 + } + }, + "Phoenix.Transports.LongPoll.Server": { + "broadcast_from!/3:129": { + "line": 129, + "guard": "is_binary(client_ref)", + "pattern": "state, client_ref, msg", + "kind": "defp", + "end_line": 130, + "ast_sha": "0882e4f8e008faa7703b4033e499221859a9c90bb7afb3b47efb0201d1a8c1fc", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "5f9f48f3d63887f9f550817a361c8f87c91cae943a22fde345425d670379b45f", + "start_line": 129, + "name": "broadcast_from!", + "arity": 3 + }, + "broadcast_from!/3:132": { + "line": 132, + "guard": "is_pid(client_ref)", + "pattern": "_state, client_ref, msg", + "kind": "defp", + "end_line": 133, + "ast_sha": "df20d134ad38825b9d2cf5e22162c1eae4bcb9863e09a2efcedb43f063f652fc", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "0eabf57bdc893f937fdd5da617a9a4ec6d1293d6e2a5e7dabaaf1d2515f784a3", + "start_line": 132, + "name": "broadcast_from!", + "arity": 3 + }, + "child_spec/1:4": { + "line": 4, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 862, + "ast_sha": "b6e9e21767cef3cb2d495e5bba3998954e1b8e716f0c12b30db6cb1fb7440fd0", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", + "start_line": 4, + "name": "child_spec", + "arity": 1 + }, + "code_change/3:4": { + "line": 4, + "guard": null, + "pattern": "_old, state, _extra", + "kind": "def", + "end_line": 940, + "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", + "start_line": 4, + "name": "code_change", + "arity": 3 + }, + "handle_call/3:4": { + "line": 4, + "guard": null, + "pattern": "msg, _from, state", + "kind": "def", + "end_line": 884, + "ast_sha": "d154285ffa31c40a154abcc529ee5f8e6b815c60b9c4c00bbba52fd368dd5b68", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", + "start_line": 4, + "name": "handle_call", + "arity": 3 + }, + "handle_cast/2:4": { + "line": 4, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 929, + "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", + "start_line": 4, + "name": "handle_cast", + "arity": 2 + }, + "handle_info/2:105": { + "line": 105, + "guard": null, + "pattern": "message, state", + "kind": "def", + "end_line": 119, + "ast_sha": "9dffc606af15ac1825a571031be42d523e2651b2c85da452343f4a392a95f8af", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "204655877c295719af91c735a37f208c64872caa3be2daef60249eaa94629e22", + "start_line": 105, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:48": { + "line": 48, + "guard": null, + "pattern": "{:dispatch, client_ref, {body, opcode}, ref}, state", + "kind": "def", + "end_line": 66, + "ast_sha": "f42a34a399decb4203335d9b331b29584b8299c0c49a6e19187ec7d4e23b3666", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "940b2f1aff462608fbf331ef64baaa327d2cd8b76e280399afc51aa2b6d941eb", + "start_line": 48, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:70": { + "line": 70, + "guard": null, + "pattern": "{:subscribe, client_ref, ref}, state", + "kind": "def", + "end_line": 72, + "ast_sha": "df1e159f6895355bfcafbd66917ff9eeff7267d22eacca7d1e23653044d20815", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "06d27e2baed086aca33eaa5d86e81fb4ec94f386a51d5286c5bacea416f26426", + "start_line": 70, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:75": { + "line": 75, + "guard": null, + "pattern": "{:flush, client_ref, ref}, state", + "kind": "def", + "end_line": 82, + "ast_sha": "35dfde4d29f0010151e10ba5ac871455c9e034487ceeaabfc5624aa9b0f1159a", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "2f61446933f8972ee45cdf3643081d8582b529ca0742ad8324f102b67e914c70", + "start_line": 75, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:86": { + "line": 86, + "guard": null, + "pattern": "{:expired, client_ref, ref}, state", + "kind": "def", + "end_line": 92, + "ast_sha": "ffefce60ebe41d4780083b7ab77f27970639a996cf5fb0d28c73b333b0d669de", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "ca1c1bcdb7f363cda958fd2ca20b6c9c64330c75f7dd0226c53087a8e59d4d29", + "start_line": 86, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:96": { + "line": 96, + "guard": null, + "pattern": ":shutdown_if_inactive, state", + "kind": "def", + "end_line": 101, + "ast_sha": "74f2bf736ae59b584ac93898578e12f27075552c1878f9b95b5e61e5f7d421ad", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "1d95cf1253efd99dc4c07815bf2297fee184b78662f5018c2525621f8b91d382", + "start_line": 96, + "name": "handle_info", + "arity": 2 + }, + "init/1:11": { + "line": 11, + "guard": null, + "pattern": "{endpoint, handler, options, params, priv_topic, connect_info}", + "kind": "def", + "end_line": 43, + "ast_sha": "cd9f8e100072620bd66065c1c3e55c6bf9d0930d41923dc5ade0f4bfa55d7790", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "e20c52ef73c3cf535acf6567cfaeba22228ea9408746fca862820211863b1a0b", + "start_line": 11, + "name": "init", + "arity": 1 + }, + "notify_client_now_available/1:149": { + "line": 149, + "guard": null, + "pattern": "state", + "kind": "defp", + "end_line": 152, + "ast_sha": "b178042e7357a0e5345c0fa766f7862961eb4b913d04e43e8e2902c9d0ab3bfe", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "e3496845b0b71a2c31b70e426666b4602a9aafe2674f2252192d8b2773ab08bf", + "start_line": 149, + "name": "notify_client_now_available", + "arity": 1 + }, + "now_ms/0:156": { + "line": 156, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 156, + "ast_sha": "c2e635558108b34d89887a7285e4a2a6c0ec0e5f69bab3d82a5d1d972542afb8", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "2168725c05e76dc59d568394ecaae806ffb3d84d4ee471c8675d1e443a63ec75", + "start_line": 156, + "name": "now_ms", + "arity": 0 + }, + "publish_reply/2:135": { + "line": 135, + "guard": "is_map(reply)", + "pattern": "state, reply", + "kind": "defp", + "end_line": 141, + "ast_sha": "64c1daf5640ea08f11211e2a686230468f8557499fcc638d4deed94b0742a4fd", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "cd249f6fe48f1199e6e7e6c515914b08041d80d041f088ee04b916df05269057", + "start_line": 135, + "name": "publish_reply", + "arity": 2 + }, + "publish_reply/2:144": { + "line": 144, + "guard": null, + "pattern": "state, reply", + "kind": "defp", + "end_line": 146, + "ast_sha": "3481cca10b5ed90f47f0360b333286c522a8a845e9f448288678019d0f0d34fa", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "2d32779f635a850f948a7eefb986f958d42da77ed9dd64e4d3226d1ce367416c", + "start_line": 144, + "name": "publish_reply", + "arity": 2 + }, + "schedule_inactive_shutdown/1:158": { + "line": 158, + "guard": null, + "pattern": "window_ms", + "kind": "defp", + "end_line": 159, + "ast_sha": "2c138af0c4b88ea154149917e13200e939bbc98be2e328b49085a45477df925c", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "1813f6d3e71eeb4f36036a86e0af2475e6a7c438616cde3788843cd93c7820e1", + "start_line": 158, + "name": "schedule_inactive_shutdown", + "arity": 1 + }, + "start_link/1:7": { + "line": 7, + "guard": null, + "pattern": "arg", + "kind": "def", + "end_line": 8, + "ast_sha": "5f13b4d4cf59c3791ecf0e6896b77bdd86dd1c2c62ff88515286fb0087180570", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "0aeb13552dc5379a6d33464ab9c4b0de64d1b892deb0c1d7726f66bb188fa46b", + "start_line": 7, + "name": "start_link", + "arity": 1 + }, + "terminate/2:123": { + "line": 123, + "guard": null, + "pattern": "reason, state", + "kind": "def", + "end_line": 125, + "ast_sha": "33b582c17fb56303f28e80811e59555d2b4a4e9666a3640c9d1c3f3cc2651db4", + "source_file": "lib/phoenix/transports/long_poll_server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", + "source_sha": "92d07954ae2170431cc34ae80a716b34df5fa2108697845d9dbcbbc5921cda65", + "start_line": 123, + "name": "terminate", + "arity": 2 + } + }, + "Plug.Exception.Phoenix.ActionClauseError": { + "__impl__/1:69": { + "line": 69, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 69, + "ast_sha": "e3f2237efa36a7849b77d5da300b6de95b75f921b007de05bbe1549428db123b", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "7673a338de29039113f06428539301e66d2653703194481aa09987af68928136", + "start_line": 69, + "name": "__impl__", + "arity": 1 + }, + "actions/1:71": { + "line": 71, + "guard": null, + "pattern": "_", + "kind": "def", + "end_line": 71, + "ast_sha": "cd9a1ecf3037be6bf542dbbbf970b1538abea2533a8a8759803a3870342601ce", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "44ae2878a59fd5377a2ccec6625b3f6663fa63d92176bce3fb83efc3cd73e2e5", + "start_line": 71, + "name": "actions", + "arity": 1 + }, + "status/1:70": { + "line": 70, + "guard": null, + "pattern": "_", + "kind": "def", + "end_line": 70, + "ast_sha": "037fd48b4767ef7491dd1f8eea9af6ffb37c79fcbc09465d86cfd2c7d6f8bd68", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "4e5608efe32e7cac74db1f8684121648721d7f67f846bf825a86b4bf67652fc9", + "start_line": 70, + "name": "status", + "arity": 1 + } + }, + "Phoenix.NotAcceptableError": { + "__struct__/0:15": { + "line": 15, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 15, + "ast_sha": "56bb5050646cb7904fa46d58afa7900cc0d449380e4083108d111b5be2e59f66", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", + "start_line": 15, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:15": { + "line": 15, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 15, + "ast_sha": "d49d6929d799d6a3c55c7cd83949e797cab094762d0109a9d7f600e14f003d24", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", + "start_line": 15, + "name": "__struct__", + "arity": 1 + }, + "exception/1:15": { + "line": 15, + "guard": "is_list(args)", + "pattern": "args", + "kind": "def", + "end_line": 15, + "ast_sha": "ac1551bd7821466ef6422bbcddd9b63f298fec85dec90490f13cd4e3dcd9a53c", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", + "start_line": 15, + "name": "exception", + "arity": 1 + }, + "message/1:15": { + "line": 15, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 15, + "ast_sha": "1a55e71ad2c4b00984c0ea1502576b3d74d57d2930b0f0a587f122efb16738d3", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", + "start_line": 15, + "name": "message", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Release": { + "docker_instructions/0:208": { + "line": 208, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 208, + "ast_sha": "c7adad6daad081cf770d778db8ab85ebb7885a4b316e9eb28367d3ec5dd62a41", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "5eae4f8dbe814a29dcaf194a7dba8e433caa2b8ee05271f7b7e71b8ea5f55f94", + "start_line": 208, + "name": "docker_instructions", + "arity": 0 + }, + "ecto_instructions/1:200": { + "line": 200, + "guard": null, + "pattern": "app", + "kind": "defp", + "end_line": 204, + "ast_sha": "bb29a9b7c31040c4329311ed7f10c3ad0737faee14c7c331cb347a7674e730cc", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "70814f7b86161c2bb4132a904822d246903a4dffbcf32711426bc2d8fa942604", + "start_line": 200, + "name": "ecto_instructions", + "arity": 1 + }, + "ecto_sql_installed?/0:233": { + "line": 233, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 233, + "ast_sha": "4dfbee2c44c4737eb26c7b1b290f4d85be94a6f019eeeac28756e2f25a60619a", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "44572bde50a3c8d990c5ea6c3c89efd5bca9fa86424cf071f3bd4d597943b756", + "start_line": 233, + "name": "ecto_sql_installed?", + "arity": 0 + }, + "elixir_and_debian_vsn/2:242": { + "line": 242, + "guard": null, + "pattern": "elixir_vsn, otp_vsn", + "kind": "defp", + "end_line": 253, + "ast_sha": "30108abdbe6acca181f8f2e08a60749dab2dd1e3a6ff572afb65de272ad66bd6", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "4864f5ec66929d8197142fddbaa4f32aeb990fa6ecf8200855fa79fcf5515253", + "start_line": 242, + "name": "elixir_and_debian_vsn", + "arity": 2 + }, + "ensure_app!/1:311": { + "line": 311, + "guard": null, + "pattern": "app", + "kind": "defp", + "end_line": 315, + "ast_sha": "9e5d17f833c592fa94823585e6c3caee2e9ccec25044b01f15c59d016e5975cd", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "5432eaa5684589bc4716e4e07a8661a0a1dd8c2934955746c1cd6893797e1c82", + "start_line": 311, + "name": "ensure_app!", + "arity": 1 + }, + "fetch_body!/1:319": { + "line": 319, + "guard": null, + "pattern": "url", + "kind": "defp", + "end_line": 358, + "ast_sha": "84454d18ae3ac7fc64386fc92cc8271ed7f7ed823f36f9b4e6f77fa61f59ad76", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "c219b97a54b752548a687f2ca5ef0b581540af6e26ff8d301d8e36e043501bb3", + "start_line": 319, + "name": "fetch_body!", + "arity": 1 + }, + "gen_docker/2:258": { + "line": 258, + "guard": null, + "pattern": "binding, opts", + "kind": "defp", + "end_line": 305, + "ast_sha": "e8fae4feccbf65e1830836c8e905da03edde3c4ee8f06f34902fe8e9a1470d63", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "51e3b5d9166e48209b8182561277821e74077cd9fb3c2279659276713f5cda92", + "start_line": 258, + "name": "gen_docker", + "arity": 2 + }, + "otp_vsn/0:366": { + "line": 366, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 376, + "ast_sha": "dd5a9d13ffe250793fa704be46aa247d3303928d0808c9dd35d073544814bb79", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "24e0327c673d1d68405566438478551e1619237621ac24c748d486ddf4f26eda", + "start_line": 366, + "name": "otp_vsn", + "arity": 0 + }, + "parse_args/1:186": { + "line": 186, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 197, + "ast_sha": "7c0c0ece3bbb3ec2c452a3a468f143f46a0551cbd6b13455028937b7d1b23cb5", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "9a4997ba5d91aa6f70cba3e4005fd106ac30e5e67d267e7b408044405860fb16", + "start_line": 186, + "name": "parse_args", + "arity": 1 + }, + "paths/0:219": { + "line": 219, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 219, + "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", + "start_line": 219, + "name": "paths", + "arity": 0 + }, + "post_install_instructions/3:223": { + "line": 223, + "guard": null, + "pattern": "path, matching, msg", + "kind": "defp", + "end_line": 229, + "ast_sha": "5a7e484f60b79598ff73e3a185e03d5c0f103ce01e8b5a41cad633bbdf92a6f3", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "64ecd96b406a989aa8155452b53f5094f235cc36720333d76571a6c8e4efcbb1", + "start_line": 223, + "name": "post_install_instructions", + "arity": 3 + }, + "protocol_versions/0:361": { + "line": 361, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 363, + "ast_sha": "cb1de9690d1b5e421a1bbec56f94b8d7f60b875bae57bbe2404b64f3b58ec822", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "4979acdeec3f4047b7f19e03be42ad07c1fbf8961abbc3bde3c126bd73946755", + "start_line": 361, + "name": "protocol_versions", + "arity": 0 + }, + "run/1:80": { + "line": 80, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 180, + "ast_sha": "807678791f0f45cff7cf9382ba817cf11426f877ab41285e001ae7035a086e6a", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "c72418fc9b28e06d8b52607bc7ee3059a3572d8946925b200a6560aec101e22d", + "start_line": 80, + "name": "run", + "arity": 1 + }, + "socket_db_adaptor_installed?/0:235": { + "line": 235, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 238, + "ast_sha": "8c6c7d9664d94c5696f5759b76736e1969219d036eb9f381fca6eb33a753975d", + "source_file": "lib/mix/tasks/phx.gen.release.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", + "source_sha": "d14bfa11378e250a2def3c9aa39f0a47d8052fc6ed7c2ffcbfe48eb491a20bcd", + "start_line": 235, + "name": "socket_db_adaptor_installed?", + "arity": 0 + } + }, + "Phoenix.Endpoint.SyncCodeReloadPlug": { + "call/2:18": { + "line": 18, + "guard": null, + "pattern": "conn, {endpoint, opts}", + "kind": "def", + "end_line": 18, + "ast_sha": "05a97e9e1a3731f6a11357fb67d37983d878b549d8e015712cf9a2736588c26e", + "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_sha": "c2a739704df8abfb9ec35f5cc3bf36d859254bbee6757913662b1f5f3155d397", + "start_line": 18, + "name": "call", + "arity": 2 + }, + "do_call/4:20": { + "line": 20, + "guard": null, + "pattern": "conn, endpoint, opts, retry?", + "kind": "defp", + "end_line": 32, + "ast_sha": "b14c198edd6e82d7450061ed3a857548f43f82f71ce62c99c3bfdba42d3ff00e", + "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_sha": "1e5d31bb135f070afdb1301036e311fe9762890aac48c2662a3a8e0e4f52e1eb", + "start_line": 20, + "name": "do_call", + "arity": 4 + }, + "init/1:16": { + "line": 16, + "guard": null, + "pattern": "{endpoint, opts}", + "kind": "def", + "end_line": 16, + "ast_sha": "20f1b5f461a9328fc607904ed80575196927b4bee39127c71f6c3b232d08a1d1", + "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", + "source_sha": "d3c3e24e0fbc098e3062a50c4a605c48ed39619db6811460c364875c60fb2d38", + "start_line": 16, + "name": "init", + "arity": 1 + } + }, + "Phoenix.Param.Any": { + "__deriving__/3:96": { + "line": 96, + "guard": null, + "pattern": "module, struct, options", + "kind": "defmacro", + "end_line": 116, + "ast_sha": "aca6de9f6e69c2e3cc61322390661f34e1a64d4995a732388a170bc8c4b8617d", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "afce5f22d361ce7ed72176cafe08e3c34defb6dcfa7680774bc36fb3e78af22f", + "start_line": 96, + "name": "__deriving__", + "arity": 3 + }, + "__impl__/1:95": { + "line": 95, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 95, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "9a820ad472710dbdd14b89e270413abac90449492fd49338a15b308053c6170c", + "start_line": 95, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:121": { + "line": 121, + "guard": null, + "pattern": "%{id: nil}", + "kind": "def", + "end_line": 122, + "ast_sha": "d0e5c57a7cbecdeb0bd816c35f78345495c34c37beda3e1b96c6c977621cf9a1", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "79c97f1f98dbf12a37d02e8d72aba4a1f485fec22fcffbc2b5bf2bd281ffbcf9", + "start_line": 121, + "name": "to_param", + "arity": 1 + }, + "to_param/1:125": { + "line": 125, + "guard": "is_integer(id)", + "pattern": "%{id: id}", + "kind": "def", + "end_line": 125, + "ast_sha": "8ca6b204a35a6fbd5ae33bb2b7bf5107843239636985740c50cd023c9d0abd22", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "686bd5c91229667b3b4262a0faf36a33d57f4341209df4007be21fd65f7354a8", + "start_line": 125, + "name": "to_param", + "arity": 1 + }, + "to_param/1:126": { + "line": 126, + "guard": "is_binary(id)", + "pattern": "%{id: id}", + "kind": "def", + "end_line": 126, + "ast_sha": "297ef37fd78aa6b75a586dc942ea0b61edbb943ab0e4dcdd8476591b9f9c5f91", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "faea66b7b0170e6a4ba8f2f2c166ed95587c7061216c4a2574e6ceb4a473c23f", + "start_line": 126, + "name": "to_param", + "arity": 1 + }, + "to_param/1:127": { + "line": 127, + "guard": null, + "pattern": "%{id: id}", + "kind": "def", + "end_line": 127, + "ast_sha": "fabf2e9a9120ae922fa2f5c4b57f61f3bc13e334e72d0abef75c6f59c525e4ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "c9fdeae5374fe91de33a7c1ccee8eeba55bc3f30b66c5aa78985d83fb60d0c77", + "start_line": 127, + "name": "to_param", + "arity": 1 + }, + "to_param/1:129": { + "line": 129, + "guard": "is_map(map)", + "pattern": "map", + "kind": "def", + "end_line": 133, + "ast_sha": "45c5ac2176a244263a0fd08150596eba96f92e7a8297d504d11e2477d2133571", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "e7d8461d237b4ada5abcc8b3c51dc2bf935993d2b799750e12c336a4df8ae7ec", + "start_line": 129, + "name": "to_param", + "arity": 1 + }, + "to_param/1:136": { + "line": 136, + "guard": null, + "pattern": "data", + "kind": "def", + "end_line": 137, + "ast_sha": "ceff7b724151d9bbe2eef567fb7baba53aa210272ce782b4f261032fff1c955d", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "03686fdddfebef033425200c9fc3cc266a00e0a61a8df81bb0c4703ba7bc35d1", + "start_line": 136, + "name": "to_param", + "arity": 1 + } + }, + "Phoenix.Socket.Reply": { + "__struct__/0:68": { + "line": 68, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 68, + "ast_sha": "acd35a2ebf5a8237fc33ea6bdec216e8f65bed2968f9172a6556430067da01f1", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "9e833359d6ac4f243e0f7935cdfda47309ef8ec9924378bd7a3f134924277290", + "start_line": 68, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:68": { + "line": 68, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 68, + "ast_sha": "50f6979e1713136ecd3a45bb43a0193973b22b1a8f25acd4156d4b3491834b3d", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "9e833359d6ac4f243e0f7935cdfda47309ef8ec9924378bd7a3f134924277290", + "start_line": 68, + "name": "__struct__", + "arity": 1 + } + }, + "Phoenix.ChannelTest": { + "fetch_test_supervisor!/1:276": { + "line": 276, + "guard": null, + "pattern": "options", + "kind": "defp", + "end_line": 288, + "ast_sha": "e830dec93b6a349234da11351daa93dfcedb0d90b11e0b072fea04b2411ca6cf", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "b0e8f163acd3c5fea1ba65ef6e86b2bede7030516fa34716ea710ea18f374487", + "start_line": 276, + "name": "fetch_test_supervisor!", + "arity": 1 + }, + "join/3:416": { + "line": 416, + "guard": "is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, topic, payload", + "kind": "def", + "end_line": 417, + "ast_sha": "c98d02e949016cf8e82e96ab1aced9de1612913a60de29ef3f0d8eeb519f9d36", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "7dcc836f31251e3f7564cbc2ac81cfc32c512a1e4d54ae5e924f6423fc84b3d7", + "start_line": 416, + "name": "join", + "arity": 3 + }, + "socket/4:235": { + "line": 235, + "guard": null, + "pattern": "socket_module, socket_id, socket_assigns, options", + "kind": "defmacro", + "end_line": 236, + "ast_sha": "c256c5b3b0d3febba238bdeb621493059cc6e7c20a1f11f0ceb43f1f727c3f3d", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "106db6eb1120d4f7182c70668e55b3cc708867970b689affa608ce9503b3e031", + "start_line": 235, + "name": "socket", + "arity": 4 + }, + "refute_broadcast/2:672": { + "line": 672, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 672, + "ast_sha": "aeb8f96f269e883eafe5786bc6ddbf96bfc80664a7d8c05108f4834116fe181d", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "cc3103c76bd35e7caac76d25b4418f7402546903981410002133ab4aba17d17a", + "start_line": 672, + "name": "refute_broadcast", + "arity": 2 + }, + "refute_broadcast/3:672": { + "line": 672, + "guard": null, + "pattern": "event, payload, timeout", + "kind": "defmacro", + "end_line": 675, + "ast_sha": "a8bd35df6c4bcfb2cebf9138ce6192fefddacfeb165c41934752dcb93afa3817", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "f081eb83b702afaf26611476255264f38cc08e4344f32ef9cbe80017e5f00455", + "start_line": 672, + "name": "refute_broadcast", + "arity": 3 + }, + "__stringify__/1:701": { + "line": 701, + "guard": null, + "pattern": "%{} = params", + "kind": "def", + "end_line": 702, + "ast_sha": "255a5ae107dfb0562a6d0bd4ac29b0d341e0b0b54bae04b88391dc3edf0a7b02", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "a83a7abf3230b564d372b2ffebfcbc6040a21c2a504742cb4f6b9b0c8e57b379", + "start_line": 701, + "name": "__stringify__", + "arity": 1 + }, + "broadcast_from!/3:525": { + "line": 525, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket, event, message", + "kind": "def", + "end_line": 527, + "ast_sha": "ed61a4400524b57cab8badea21c025a531524b58c86384ad29f5530fadd732e8", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "27426976b9ce706b5a685f1c216e434d453320671ed0d82852090862ee3006ec", + "start_line": 525, + "name": "broadcast_from!", + "arity": 3 + }, + "subscribe_and_join!/3:357": { + "line": 357, + "guard": "is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, topic, payload", + "kind": "def", + "end_line": 359, + "ast_sha": "be6ed4510adedcc85ecb318a3663545662275de56ff9dcf93f53a708e9f34f5d", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "fe6c134bf0ec7022744c3237efe2763ce0868e2fe4889d8d3ae50f96ad4f6f44", + "start_line": 357, + "name": "subscribe_and_join!", + "arity": 3 + }, + "socket/1:208": { + "line": 208, + "guard": null, + "pattern": "socket_module", + "kind": "defmacro", + "end_line": 209, + "ast_sha": "ca842178fe8458f81072c09e67c4cd5ff042aaa258f3260428c7f1d7960b7e50", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "a18bdd8b2b7405d2cd5c3c00a1914ac13fc2cfcdd6fc113f89cdcbd95348b040", + "start_line": 208, + "name": "socket", + "arity": 1 + }, + "assert_broadcast/2:654": { + "line": 654, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 654, + "ast_sha": "8bf20c36a7f177cf0972ff47dd6a794dd8fdba0428a913135b13be3d3eb4373a", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "c1ae207c46507efdf86035a01b6d27c626f26eb510828ab6a752b2463877089c", + "start_line": 654, + "name": "assert_broadcast", + "arity": 2 + }, + "first_socket!/1:269": { + "line": 269, + "guard": null, + "pattern": "endpoint", + "kind": "defp", + "end_line": 272, + "ast_sha": "656d8e32b7e2fb127afccb6a05d81fd00cf71506e8fb7e8bd84e5df9df8db612", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "4dcc7c9b7911955bd55b07c43aa8ff4870830eac92f6796c0b1bdeaa8ca79efb", + "start_line": 269, + "name": "first_socket!", + "arity": 1 + }, + "join/4:428": { + "line": 428, + "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", + "kind": "def", + "end_line": 456, + "ast_sha": "6ed35babba52ba91b954a05a696371a1df29a4dd4637a28d7168adadd3da0fc4", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "b62718e08538baf1c82094448156942d5f462bcd9b76c2f8c6975e14aa181172", + "start_line": 428, + "name": "join", + "arity": 4 + }, + "match_topic_to_channel!/2:679": { + "line": 679, + "guard": null, + "pattern": "socket, topic", + "kind": "defp", + "end_line": 694, + "ast_sha": "786e30035901ac33e91a1cdd0ed2da734e477bdfb4983846e95780f240b74083", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "361133c3e3037413f68dbce69c7410303cb43b77da3b5ead92ac9e71c650a55f", + "start_line": 679, + "name": "match_topic_to_channel!", + "arity": 2 + }, + "__connect__/4:326": { + "line": 326, + "guard": null, + "pattern": "endpoint, handler, params, options", + "kind": "def", + "end_line": 348, + "ast_sha": "41ee570a08b58f96655426ed37c4bcee62598ee886ba010c67f800dc47f4981a", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "e9b5f1eb244262420c425b9e22e51952e0baca3adfc0ad3869257646965d4ec6", + "start_line": 326, + "name": "__connect__", + "arity": 4 + }, + "refute_reply/3:626": { + "line": 626, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 626, + "ast_sha": "021c0f97980f9d1dd869a2f57a60d10b20bca8dd836c99c6555430cdebdb5627", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "8fae7916f4434663b7704146aa3f6597f56a5ea37bd1da5b4d5b74a0f8c80992", + "start_line": 626, + "name": "refute_reply", + "arity": 3 + }, + "refute_reply/2:626": { + "line": 626, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 626, + "ast_sha": "2a66b3223461c7339e6cedc6ea4112ddd3278cff5e0ae6d2b6cd022855f0f7f0", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "8fae7916f4434663b7704146aa3f6597f56a5ea37bd1da5b4d5b74a0f8c80992", + "start_line": 626, + "name": "refute_reply", + "arity": 2 + }, + "refute_push/2:581": { + "line": 581, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 581, + "ast_sha": "d8abf3b8fec8769c848f9e58d5ae66ff6643c2ad32ab4b465320059e4150f958", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "8b8ce3c9b00667451718a39b6deb73a1998bc505ea7013e5f64ee449f8de8f89", + "start_line": 581, + "name": "refute_push", + "arity": 2 + }, + "subscribe_and_join!/3:369": { + "line": 369, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 369, + "ast_sha": "a57c7cf3133b778fe65fa6f11c1e4ce383143ddb8470f922b764d7be31068ab3", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "2441eee163534ec1de73456914c357a39fda794d23f7678fd9c6e544d50e3f11", + "start_line": 369, + "name": "subscribe_and_join!", + "arity": 3 + }, + "close/1:501": { + "line": 501, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 501, + "ast_sha": "5479b2099f89986600871c22e5ae7f7634369508d542032f3c5a1f36e69e6307", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "4fa337a7b80641b04850ea79f4e238c6dda12f866e24787c671d4bc575b06e84", + "start_line": 501, + "name": "close", + "arity": 1 + }, + "assert_reply/2:604": { + "line": 604, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 604, + "ast_sha": "efc4bdbfc72e33dca0a7f596d2152d480975a10c04d0f6cfd7c9f46075c69b83", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "0a69a7ddd645f22c15e83bc209eff765a2f88e12be1373098140fb09b7d81d8d", + "start_line": 604, + "name": "assert_reply", + "arity": 2 + }, + "close/2:501": { + "line": 501, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket, timeout", + "kind": "def", + "end_line": 502, + "ast_sha": "b328b4e378ee6223b318f2672e714c9c86719df925af7efb2fb69e84a2b850ec", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "9cd3c8139b05f1e4f817eb377516c9b260b0050bdedeb0f048792677b940cda5", + "start_line": 501, + "name": "close", + "arity": 2 + }, + "refute_push/3:581": { + "line": 581, + "guard": null, + "pattern": "event, payload, timeout", + "kind": "defmacro", + "end_line": 585, + "ast_sha": "db913e5ad782d5f0069e39b0915112bb325e541f3b653e8bdc915626f876c59b", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "f7cced920138e97929810d9c152bfa83716708f72963b35f95c82fe3720fe10c", + "start_line": 581, + "name": "refute_push", + "arity": 3 + }, + "assert_broadcast/3:654": { + "line": 654, + "guard": null, + "pattern": "event, payload, timeout", + "kind": "defmacro", + "end_line": 657, + "ast_sha": "2cc76a3a0182b89e3c9e5a667d0e54036e425b84f942700d6b24cb9c7c6ab427", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "456b7e223c81be0fa2ab18c2e91440db1ae957919be61f07529ba4fb2c0283c1", + "start_line": 654, + "name": "assert_broadcast", + "arity": 3 + }, + "assert_reply/4:604": { + "line": 604, + "guard": null, + "pattern": "ref, status, payload, timeout", + "kind": "defmacro", + "end_line": 610, + "ast_sha": "054ed7bdd53c1f8d658dc1457b8133289f360d4bd1424169e3941deab575b634", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "17654721110d2af5fc805af4c8e247c1f0ae9af37ab4797b2cb3ffaff82548f3", + "start_line": 604, + "name": "assert_reply", + "arity": 4 + }, + "connect/3:310": { + "line": 310, + "guard": null, + "pattern": "handler, params, options", + "kind": "defmacro", + "end_line": 321, + "ast_sha": "3a614dc1474b0a1407b1a4c45ccd96ad9241cf3aafb1dcd6668576c304f66526", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "6afe5c7a4c52a8dfdff645de8c7d2bedb7fa408d0c27dce638c3d4cb7582ec9b", + "start_line": 310, + "name": "connect", + "arity": 3 + }, + "join/3:428": { + "line": 428, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 428, + "ast_sha": "5bc059f1b9da3d6679956425ce8421497106102ebe1833368e581bb832453ac4", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "8b471f4859782316821375563635b970de121ced32729923a2baf3be93fd741c", + "start_line": 428, + "name": "join", + "arity": 3 + }, + "assert_reply/3:604": { + "line": 604, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 604, + "ast_sha": "cbad7e2c54e6ec201b75757ea9658723f3a8958170336c2e2db3eea2a7d61a5a", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "0a69a7ddd645f22c15e83bc209eff765a2f88e12be1373098140fb09b7d81d8d", + "start_line": 604, + "name": "assert_reply", + "arity": 3 + }, + "subscribe_and_join/3:404": { + "line": 404, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 404, + "ast_sha": "ffa28165f4c49bd92f5bba3710d31fda952082b788970540c7a8be9ac7c0ce0a", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "f15248e0fb996dae59e0ee06f1d52b5df96cd40ff1b0167cceaab70a24e2d0b3", + "start_line": 404, + "name": "subscribe_and_join", + "arity": 3 + }, + "__stringify__/1:699": { + "line": 699, + "guard": null, + "pattern": "%{__struct__: _} = struct", + "kind": "def", + "end_line": 700, + "ast_sha": "4b9761dbfc3bcd123717a1b7e01f1a20c5e724b682ee30613f1f50acd314c759", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "9387c493c07938300ad7514a9335640fc197981e85d6abf2612fef9ce88bf291", + "start_line": 699, + "name": "__stringify__", + "arity": 1 + }, + "__stringify__/1:703": { + "line": 703, + "guard": "is_list(params)", + "pattern": "params", + "kind": "def", + "end_line": 704, + "ast_sha": "9193c0ff46540e43a7aaaee2fb97ba681d059c86aaeb016437fd1a0df79bccb2", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "4cbf35396240ac6232f92e12fce80ad45787e5bc7dc910189d78498d1beae764", + "start_line": 703, + "name": "__stringify__", + "arity": 1 + }, + "subscribe_and_join!/2:352": { + "line": 352, + "guard": "is_binary(topic)", + "pattern": "%Phoenix.Socket{} = socket, topic", + "kind": "def", + "end_line": 353, + "ast_sha": "5449a73a921a28486e6b84273abe2805d243a4640706ae1f58c42fc72043fd71", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "42b3e8fc022aa11991192d44beee63a32fa1496b7e89be63b88f9d06cfe5fcc1", + "start_line": 352, + "name": "subscribe_and_join!", + "arity": 2 + }, + "push/3:472": { + "line": 472, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket, event, payload", + "kind": "def", + "end_line": 476, + "ast_sha": "a3e4e75773d64c8e97b25bd3b8e792ff8d912d4c2698fcf3296ad07c2cf9d2b3", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "3cc680af9db19de71b3750ec27aad630d8982e33bdddb6c11d4925305d3f2971", + "start_line": 472, + "name": "push", + "arity": 3 + }, + "socket/3:235": { + "line": 235, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 235, + "ast_sha": "ef90a6b17bb0b0f823cc47a7b5719008cedbafcd659d1763ce5a9a3d8a3b54f0", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "4fcd287e984381b4969811ab5cc8e0f23a961d42dd6954c786e91b7e66943176", + "start_line": 235, + "name": "socket", + "arity": 3 + }, + "socket/5:239": { + "line": 239, + "guard": null, + "pattern": "module, id, assigns, options, caller", + "kind": "defp", + "end_line": 251, + "ast_sha": "cbcb92a00dc8259c921507318d6a9b06de7e42627ec56a496c91a545c6e06f56", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "0a21c04bd1ccf0cbd5bfb76b0b75654ea4fcc4a3222bf216ec9e9770c8625ba6", + "start_line": 239, + "name": "socket", + "arity": 5 + }, + "broadcast_from/3:517": { + "line": 517, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket, event, message", + "kind": "def", + "end_line": 519, + "ast_sha": "d8d73246057b0eb79817be1485ce4e0e4c717b0920c0630276f51a946f4d461f", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "e08f1191f36670379588324ea1fa5578c295823e33d7d214567c7c649d1b7235", + "start_line": 517, + "name": "broadcast_from", + "arity": 3 + }, + "stringify_kv/1:708": { + "line": 708, + "guard": null, + "pattern": "{k, v}", + "kind": "defp", + "end_line": 709, + "ast_sha": "a82fb91e06f5de9f672bdd0611a733ac2c5223c22ac7810cd91220e11173a838", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "73992879ca84e8953c9cac3694c2c8136d2b68b18fa9ff0aaa86d83aa41f9c94", + "start_line": 708, + "name": "stringify_kv", + "arity": 1 + }, + "subscribe_and_join/2:378": { + "line": 378, + "guard": "is_binary(topic)", + "pattern": "%Phoenix.Socket{} = socket, topic", + "kind": "def", + "end_line": 379, + "ast_sha": "88fed2c43c5e5ebb1b4b1f941c3b845b32c7759c97cc81a44033ad7235d65825", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "ac5cf26fb286375d0a4a8e2b7d4b4e3d69e4a59ae75e9c705339258007fed796", + "start_line": 378, + "name": "subscribe_and_join", + "arity": 2 + }, + "assert_push/3:561": { + "line": 561, + "guard": null, + "pattern": "event, payload, timeout", + "kind": "defmacro", + "end_line": 565, + "ast_sha": "7128fda7a15bd465475134e4b03b17f60ff6864f0970bf4a1d5af0d1790758b0", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "91501f991edf29c99d5d057bd38e8e7b48967e356a5b13f355c32fc13c12bde0", + "start_line": 561, + "name": "assert_push", + "arity": 3 + }, + "__socket__/5:256": { + "line": 256, + "guard": null, + "pattern": "socket, id, assigns, endpoint, options", + "kind": "def", + "end_line": 265, + "ast_sha": "bca468eab7dfb97455431e087fa602248ebb2fc649c6d2a186e9f9025f16b3f6", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "122c56b025513626a36b831767c6b1fb2071cedb75c850e28c7134a69dd34979", + "start_line": 256, + "name": "__socket__", + "arity": 5 + }, + "subscribe_and_join/4:404": { + "line": 404, + "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", + "kind": "def", + "end_line": 407, + "ast_sha": "dccf9962c0cd9c060d3cbefa42574c876f822fa8c062436ef1446e321c2b4671", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "1bf2e7db59cd609cb9579221e4cb089eda218cba44d44f6ee17f3cccb5d5a30d", + "start_line": 404, + "name": "subscribe_and_join", + "arity": 4 + }, + "subscribe_and_join/3:383": { + "line": 383, + "guard": "is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, topic, payload", + "kind": "def", + "end_line": 385, + "ast_sha": "7c3531f413467e35e99d9443411ed9d25d8281112d667eb7dd35eccbab4809f2", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "a1d6fa78aa8075f7d3ea64aafe17c93079c5f65f1ac74f325b1a192449d53a10", + "start_line": 383, + "name": "subscribe_and_join", + "arity": 3 + }, + "__using__/1:177": { + "line": 177, + "guard": null, + "pattern": "_", + "kind": "defmacro", + "end_line": 186, + "ast_sha": "fbbf561bf066a2065d5e5cafab58d4d6c7f769788a82bb16dc56b19285df66d3", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "7cd4e4c479b66c1cb3a53a01521d19d77bbc6b581355415fe510d7fda7a7c4be", + "start_line": 177, + "name": "__using__", + "arity": 1 + }, + "__stringify__/1:705": { + "line": 705, + "guard": null, + "pattern": "other", + "kind": "def", + "end_line": 706, + "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "863b7454af46fca7b60ff5069047471fb473ea9795cbbe0d9f7c726cc0980fcf", + "start_line": 705, + "name": "__stringify__", + "arity": 1 + }, + "push/2:472": { + "line": 472, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 472, + "ast_sha": "e6f7cc4e18f7f6521a95a6dfd63f7fcbfd278ca01ea6e14b61b28019b4a161b5", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "7e70ea5113393916d1f45c1252768ea2d46e1f001d61467faf6f88782137629c", + "start_line": 472, + "name": "push", + "arity": 2 + }, + "leave/1:487": { + "line": 487, + "guard": null, + "pattern": "%Phoenix.Socket{} = socket", + "kind": "def", + "end_line": 488, + "ast_sha": "8523ce3d65c95d31a950b6a38ea8ec7e639ead3845b56d512d9343a04c5821e0", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "6885f0f2558399b5e0ffdfaf60c448860c215f7902a29171556275470a525c52", + "start_line": 487, + "name": "leave", + "arity": 1 + }, + "refute_reply/4:626": { + "line": 626, + "guard": null, + "pattern": "ref, status, payload, timeout", + "kind": "defmacro", + "end_line": 632, + "ast_sha": "9dc01cbaebd558572676e412967d133c768c2f94e9fa742f4b1cfa4f35747849", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "9ea9874b4e5b6ede0af859aa26944e93a3cb39cfc4a704eea881388f61f822d8", + "start_line": 626, + "name": "refute_reply", + "arity": 4 + }, + "socket/2:300": { + "line": 300, + "guard": null, + "pattern": "id, assigns", + "kind": "defmacro", + "end_line": 301, + "ast_sha": "97935aca95c9990d97f75765e1c7f37460b1eae74ae2682dbc79d162f7e061d0", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "83c4be91a8ca7a8a34282297938050bdc5ddb2c85632565de10086827546ebac", + "start_line": 300, + "name": "socket", + "arity": 2 + }, + "connect/2:310": { + "line": 310, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 310, + "ast_sha": "c7cb4ab995a062ecff873d2074f7dc0859b3b0ee341956c5beee454858e547b9", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "b1ba6f2f1f42270c09c4184b64851989723a1ee125459c7785a7cf0a9e23a477", + "start_line": 310, + "name": "connect", + "arity": 2 + }, + "subscribe_and_join!/4:369": { + "line": 369, + "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", + "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", + "kind": "def", + "end_line": 373, + "ast_sha": "11ba779714babf316a5558b08e469afd48192832e57d5052c86cf5ab5b1a109c", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "518723426fb0d2bc3d472e4c871b2edf17c9b1b7a3a032dd91fc3378fd096ad9", + "start_line": 369, + "name": "subscribe_and_join!", + "arity": 4 + }, + "assert_push/2:561": { + "line": 561, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 561, + "ast_sha": "1a4817a1d98e86caccd29794b8a6a9349e2c3a0bf84d83499ea42b7d15c3d42d", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "09d7a4a399efc212870baca6ef28ffce03d36acfe3c57abd7fb244d6022a2e28", + "start_line": 561, + "name": "assert_push", + "arity": 2 + }, + "socket/0:294": { + "line": 294, + "guard": null, + "pattern": "", + "kind": "defmacro", + "end_line": 295, + "ast_sha": "d03043df313a25291caf53e9dc0fc3a2b619a57c3f206555ceedb46e8c4537f7", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "af68f9db2d4814599b89386da51bc7a9be5067d96252333f256feb8ff204c62c", + "start_line": 294, + "name": "socket", + "arity": 0 + }, + "join/2:411": { + "line": 411, + "guard": "is_binary(topic)", + "pattern": "%Phoenix.Socket{} = socket, topic", + "kind": "def", + "end_line": 412, + "ast_sha": "31ca8ffe7b3b888ccc0c29dfdd911bc481aa56070efc2e78f1a4c900c78980f6", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "a717e13398f910a18d77c14d8ea5aa4cca54c093c4dc07b417fd81dde37d7eb7", + "start_line": 411, + "name": "join", + "arity": 2 + } + }, + "Phoenix.Transports.LongPoll": { + "broadcast_from!/3:246": { + "line": 246, + "guard": "is_binary(topic)", + "pattern": "endpoint, topic, msg", + "kind": "defp", + "end_line": 247, + "ast_sha": "890b25645d84fb258ff0cf484115ce5d14ba8062d9cfa07920585ee84fea0d05", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "a15fe8336045d6e69517c5ebb2c5aac58bd85e06a90d98372c0c4c535f6e2240", + "start_line": 246, + "name": "broadcast_from!", + "arity": 3 + }, + "broadcast_from!/3:249": { + "line": 249, + "guard": "is_pid(pid)", + "pattern": "_endpoint, pid, msg", + "kind": "defp", + "end_line": 250, + "ast_sha": "cd5c534c4cde053164cb27a14ed51e994a8927d64b63cb2803c4a0fa7efa2ca2", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "f6fcfd5a8ea9e6e0850517d542fd37da434ffb37f377abeecee923abde6b938c", + "start_line": 249, + "name": "broadcast_from!", + "arity": 3 + }, + "call/2:25": { + "line": 25, + "guard": null, + "pattern": "conn, {endpoint, handler, opts}", + "kind": "def", + "end_line": 32, + "ast_sha": "6ebba8351f12b476a934fcd9fea9e06249a31892f8ae3a564dfc0cabfff6a155", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "dca83e5e634826e19f47dd63786392952849ec7858ef74d29d18386c04964d89", + "start_line": 25, + "name": "call", + "arity": 2 + }, + "client_ref/1:231": { + "line": 231, + "guard": "is_binary(topic)", + "pattern": "topic", + "kind": "defp", + "end_line": 231, + "ast_sha": "5bb3c38d912680cb653db0f597424fd0b5c40073d822dfe470d89a0f9db122af", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "9325454a425ee5087fb0d6cec03c7f74a28a42b6603bcf27d95d4d67337a26fb", + "start_line": 231, + "name": "client_ref", + "arity": 1 + }, + "client_ref/1:232": { + "line": 232, + "guard": "is_pid(pid)", + "pattern": "pid", + "kind": "defp", + "end_line": 232, + "ast_sha": "f29b2ed947a6b88e9227df6493c7bb1dd125545fd0f695ce069723dbf3dd3105", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "6432a343173dacbdc7453fa921b8f9119ff52310181c0b24c7d067cecf648772", + "start_line": 232, + "name": "client_ref", + "arity": 1 + }, + "default_config/0:12": { + "line": 12, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 12, + "ast_sha": "e8a070ecb4f398f76a58fda9411442165845918f93c2aec27bbc22f1c046cc44", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "6975dacee86c58c3c40b7493f51c483a5c6cbf4638f425fdf46b56581003560f", + "start_line": 12, + "name": "default_config", + "arity": 0 + }, + "dispatch/4:35": { + "line": 35, + "guard": null, + "pattern": "%{halted: true} = conn, _, _, _", + "kind": "defp", + "end_line": 36, + "ast_sha": "410a16737bc218390963f2002f00bc57ae72f0f8938a1f70046d14b20cb8be45", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "2171e52d22529bacc627fed981185672aff91c5bc477cf0b10b6382bcb3fd62f", + "start_line": 35, + "name": "dispatch", + "arity": 4 + }, + "dispatch/4:41": { + "line": 41, + "guard": null, + "pattern": "%{method: \"OPTIONS\"} = conn, _, _, _", + "kind": "defp", + "end_line": 48, + "ast_sha": "153efd5d3004bf19673d69f162f296320d5af163a253f66d4796424a0fcaadce", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "fbd10a7059cfe8b9179fb2abcaf2244cf5f3da968952151962d6f165ad5813e6", + "start_line": 41, + "name": "dispatch", + "arity": 4 + }, + "dispatch/4:52": { + "line": 52, + "guard": null, + "pattern": "%{method: \"GET\"} = conn, endpoint, handler, opts", + "kind": "defp", + "end_line": 58, + "ast_sha": "44aa3287f9d3ab39c98214ad5528b5defeea9786811f56ddc579796d5da0a550", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "7bac0d50285bff876920d2b9406b698e0c6c11261fa5993bbae8513956d03f11", + "start_line": 52, + "name": "dispatch", + "arity": 4 + }, + "dispatch/4:63": { + "line": 63, + "guard": null, + "pattern": "%{method: \"POST\"} = conn, endpoint, _, opts", + "kind": "defp", + "end_line": 69, + "ast_sha": "551fed22c27516f22e59951e7fc70f88a8d8a9290cb69e5279c8bb83e5a124c5", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "49f07e8f5f76b080ee8f54359ab075a9fb981f0d74fffe0269c4fd1547da8704", + "start_line": 63, + "name": "dispatch", + "arity": 4 + }, + "dispatch/4:74": { + "line": 74, + "guard": null, + "pattern": "conn, _, _, _", + "kind": "defp", + "end_line": 75, + "ast_sha": "7f563dd08682b67a0723bd92547b9231b3c09e5ded63d460aeda42e94cba1bf1", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "93823b984420d59768cb5470e9f72d88cc15eee3c82fc3325c992853b0b3bba1", + "start_line": 74, + "name": "dispatch", + "arity": 4 + }, + "init/1:23": { + "line": 23, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 23, + "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", + "start_line": 23, + "name": "init", + "arity": 1 + }, + "listen/4:160": { + "line": 160, + "guard": null, + "pattern": "conn, server_ref, endpoint, opts", + "kind": "defp", + "end_line": 188, + "ast_sha": "8d88f6745f4d02833f376fbdd98acc084a70263c7f20eb438b08d502549b6727", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "57a2d4357574c212992ecfb836c893e74ff251de36f4f530060c4b4ad5ff5c9e", + "start_line": 160, + "name": "listen", + "arity": 4 + }, + "maybe_auth_token_from_header/2:270": { + "line": 270, + "guard": null, + "pattern": "conn, true", + "kind": "defp", + "end_line": 276, + "ast_sha": "418fd570780344c832392618fa5ebc86b57cf089e4d3f3be92d08dbb00348e95", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "fd657aac70fca7ad7d6fe7d76efdfd70acaf6db36998474650f6d89e46efc7db", + "start_line": 270, + "name": "maybe_auth_token_from_header", + "arity": 2 + }, + "maybe_auth_token_from_header/2:280": { + "line": 280, + "guard": null, + "pattern": "conn, _", + "kind": "defp", + "end_line": 280, + "ast_sha": "d418dff67505cf526abe380616091b9f20a1537b40a9770ff5b9292092c7c786", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "3465c5df608942102ca5a8d5c47d36aefaa005f81aec552c3d646fd73d7b2083", + "start_line": 280, + "name": "maybe_auth_token_from_header", + "arity": 2 + }, + "new_session/4:133": { + "line": 133, + "guard": null, + "pattern": "conn, endpoint, handler, opts", + "kind": "defp", + "end_line": 156, + "ast_sha": "262424b3455aa93115396aa917215de1fbd95939988f783ccdf4f265559a305c", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "24eaa8fbe28d0b8f2e024134aefa5cd3ec9f39b96181d8d83f5c30cfc66d9b04", + "start_line": 133, + "name": "new_session", + "arity": 4 + }, + "publish/4:78": { + "line": 78, + "guard": null, + "pattern": "conn, server_ref, endpoint, opts", + "kind": "defp", + "end_line": 107, + "ast_sha": "f6a2fcf93d7baadb013eff1f1c33b2897846d89e6de99e1ef86cf3a35427568e", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "b586f21319ac56c6b0e1cf1a87469f8a77b1a4b30c9dddcbdb8814cfb63b10b9", + "start_line": 78, + "name": "publish", + "arity": 4 + }, + "resume_session/4:193": { + "line": 193, + "guard": null, + "pattern": "%Plug.Conn{} = conn, %{\"token\" => token}, endpoint, opts", + "kind": "defp", + "end_line": 214, + "ast_sha": "897ae69b08b94b0ac4e79bc35ca56e6bed23cb7ac9f75a7fe79a268de300ab22", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "86e950de434c2b212acc4eec1858df1313137a0668be5fe9c932faa0172b47ec", + "start_line": 193, + "name": "resume_session", + "arity": 4 + }, + "resume_session/4:219": { + "line": 219, + "guard": null, + "pattern": "%Plug.Conn{}, _params, _endpoint, _opts", + "kind": "defp", + "end_line": 219, + "ast_sha": "4be6ee91cbca4d49e9f3458542a1b6b9b346ab56d719753bcce1f08cab538980", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "811dcc19d1de14d4a1931aafa3b09214934651b9a5a6390582baac4b5b653cb2", + "start_line": 219, + "name": "resume_session", + "arity": 4 + }, + "safe_decode64!/1:111": { + "line": 111, + "guard": null, + "pattern": "base64", + "kind": "defp", + "end_line": 115, + "ast_sha": "54ee7946a3a89117abba779f8df04ca9618f0b8c20febfcb61f8df5e7865ca9c", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "e60fbdd747120d67ae89933cb247fa6a1cd0b0818ac4366e8613cedad135ab22", + "start_line": 111, + "name": "safe_decode64!", + "arity": 1 + }, + "send_json/2:290": { + "line": 290, + "guard": null, + "pattern": "conn, data", + "kind": "defp", + "end_line": 293, + "ast_sha": "37b0d32c189d7e4ba0dd3011b0ad9921d019ade4428e7664d29468bf4471c26a", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "699f01e58e233a8e0e253d87139e3437de92fc4abba0e8c1dacec6ff61238a6a", + "start_line": 290, + "name": "send_json", + "arity": 2 + }, + "server_ref/4:223": { + "line": 223, + "guard": "is_pid(pid)", + "pattern": "endpoint_id, id, pid, topic", + "kind": "defp", + "end_line": 227, + "ast_sha": "1c99f00b45fdd0660e1fb20f379807df0e1f0943204a1c8c1517563bcfbfdb29", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "680c7920df406e95a188dbf11ca18d013f9518ba02719a0051f9c80d039ccfc9", + "start_line": 223, + "name": "server_ref", + "arity": 4 + }, + "sign_token/3:252": { + "line": 252, + "guard": null, + "pattern": "endpoint, data, opts", + "kind": "defp", + "end_line": 257, + "ast_sha": "176def848912098419fd5c45a16abec9a31fcd1ad3da505d8cf8d45913935985", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "0537dfb964d510605ad45f7f4ee98320e31a4158bcf1feae9f62c3ea64d5efc3", + "start_line": 252, + "name": "sign_token", + "arity": 3 + }, + "status_json/1:282": { + "line": 282, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 283, + "ast_sha": "b71ee2ebb5d3bcd89cb86662f133ca70018156aee8b94ecf169900fad21194d6", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "2c340f150529503fa855fedb251271e9e42017cc7e8927bb05fb9967dafee2a5", + "start_line": 282, + "name": "status_json", + "arity": 1 + }, + "status_token_messages_json/3:286": { + "line": 286, + "guard": null, + "pattern": "conn, token, messages", + "kind": "defp", + "end_line": 287, + "ast_sha": "5d9e1435c6cfe7abd27975540bc883d87fec7ff44572a3c1e62a23a6075af9ca", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "cc0ca9ba01f78b07567b7410db6579e5379be149eafd7f3e3e2e14df36fda25b", + "start_line": 286, + "name": "status_token_messages_json", + "arity": 3 + }, + "subscribe/2:234": { + "line": 234, + "guard": "is_binary(topic)", + "pattern": "endpoint, topic", + "kind": "defp", + "end_line": 235, + "ast_sha": "ce5a9bf43aa81b2d4863733d4ebb03efdc8f63184777f2f53266ff0ed58579fc", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "dcafa35e2faf014cc97ce70bbea56852439ccf0c79ec24c68efa1d1f42e58048", + "start_line": 234, + "name": "subscribe", + "arity": 2 + }, + "subscribe/2:237": { + "line": 237, + "guard": "is_pid(pid)", + "pattern": "_endpoint, pid", + "kind": "defp", + "end_line": 237, + "ast_sha": "5447a8e791c0f4f5d29fcbcd7acb171e1dd0ad30cd2a5cf9ba600815eb1c7582", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "ebf392a3c9f21ff8556f21036af302a3212e87c7e44ec2cda49cc1b8b320d799", + "start_line": 237, + "name": "subscribe", + "arity": 2 + }, + "transport_dispatch/4:119": { + "line": 119, + "guard": null, + "pattern": "endpoint, server_ref, body, opts", + "kind": "defp", + "end_line": 127, + "ast_sha": "6d89c4135eb889e2ebaa62672d039220c562c93991fe63b85c3717521e6d66f5", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "a9dafa5f6155d224d5e3e648b1a0d28b362c344bb247c9cbab490289baada6f1", + "start_line": 119, + "name": "transport_dispatch", + "arity": 4 + }, + "unsubscribe/2:240": { + "line": 240, + "guard": "is_binary(topic)", + "pattern": "endpoint, topic", + "kind": "defp", + "end_line": 241, + "ast_sha": "183a230562886472b79b50a1bdbceeb105dfb65adeed71439f10a6018bda684d", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "905d57b191f298005a871ebe86fe00aa41bb7fefa207207cf34784d346ea84bf", + "start_line": 240, + "name": "unsubscribe", + "arity": 2 + }, + "unsubscribe/2:243": { + "line": 243, + "guard": "is_pid(pid)", + "pattern": "_endpoint, pid", + "kind": "defp", + "end_line": 243, + "ast_sha": "d1c74e5f505222011cc2621376565b3a2da73dc59917f64c0c59309819de778d", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "4b0d8fb09d4cb5a7445357b1afc208cf6defb74190f96b468cc99d939bccdbd3", + "start_line": 243, + "name": "unsubscribe", + "arity": 2 + }, + "verify_token/3:261": { + "line": 261, + "guard": null, + "pattern": "endpoint, signed, opts", + "kind": "defp", + "end_line": 266, + "ast_sha": "71b9409e962ca4b67f3bb0113437b0a883e8b426c9b7f8db3cf6009958a9bd72", + "source_file": "lib/phoenix/transports/long_poll.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", + "source_sha": "df2a1794e91f1b26907f3c6a1f3e77bcad90c9469c37b720fe8f3de0baac69e0", + "start_line": 261, + "name": "verify_token", + "arity": 3 + } + }, + "Phoenix.Endpoint.Supervisor": { + "init/1:28": { + "line": 28, + "guard": null, + "pattern": "{otp_app, mod, opts}", + "kind": "def", + "end_line": 110, + "ast_sha": "437a2cb37a78d9d36ca74d37d6e202f7419745d35503d5e5ac9214543c918e4d", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "e428507a6754442cf8ef33d8642755e9eed138448ee330b9eeaa4831fb3870f0", + "start_line": 28, + "name": "init", + "arity": 1 + }, + "empty_string_if_root/1:392": { + "line": 392, + "guard": null, + "pattern": "other", + "kind": "defp", + "end_line": 392, + "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "c546479b480ce1ff0d55945d021d6884c0dd2fb52ce1c07079ed5477f1b1d717", + "start_line": 392, + "name": "empty_string_if_root", + "arity": 1 + }, + "server?/1:219": { + "line": 219, + "guard": "is_list(conf)", + "pattern": "conf", + "kind": "defp", + "end_line": 221, + "ast_sha": "4ec8d6168ba5e142b4757be616d54323b4f252ac80eb2fa525edf2ea8e438c40", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "91ebd2dae890c87c38dfac97e61f0396322f33559c4d4a814f7aef5be4fb2e85", + "start_line": 219, + "name": "server?", + "arity": 1 + }, + "server_children/3:182": { + "line": 182, + "guard": null, + "pattern": "mod, config, server?", + "kind": "defp", + "end_line": 197, + "ast_sha": "0eb8ebeae7304b6f65ac231c831948553a4bda8c14e30ff2742b19bab5013074", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "c83c1893217e3d7dc8a4ef0bb08949a2d954ed169b6c46545723aaf24c4e9afb", + "start_line": 182, + "name": "server_children", + "arity": 3 + }, + "config_children/3:173": { + "line": 173, + "guard": null, + "pattern": "mod, conf, default_conf", + "kind": "defp", + "end_line": 175, + "ast_sha": "8ea333adebcb34a0778eb74f4ebd5368706d11b339b285fbeeb13c2a7695e464", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "f26b29e3364650cf512ad4b85869cc3b79e799a99c420b89ee4eb6af967cac49", + "start_line": 173, + "name": "config_children", + "arity": 3 + }, + "static_cache/3:433": { + "line": 433, + "guard": null, + "pattern": "digests, value, true", + "kind": "defp", + "end_line": 434, + "ast_sha": "93ee799841760bc11e9e6fde9bd1d5880a594801f2ce884c81307d6ee20c413d", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "05c2e5bff0ac885e40b8a910a969ab7e041b51363411f23cf36bae7996382ea0", + "start_line": 433, + "name": "static_cache", + "arity": 3 + }, + "empty_string_if_root/1:391": { + "line": 391, + "guard": null, + "pattern": "\"/\"", + "kind": "defp", + "end_line": 391, + "ast_sha": "355f97ee86f192e98676e593626c55628410f8d89503582df461836864ab4f00", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "2a9c74084a9d7b5eaca921f5cba23890094308dda35106a4cc7a2b22b277acc1", + "start_line": 391, + "name": "empty_string_if_root", + "arity": 1 + }, + "start_link/3:12": { + "line": 12, + "guard": null, + "pattern": "otp_app, mod, opts", + "kind": "def", + "end_line": 23, + "ast_sha": "824fa0f310980fc9e136750d7e00d0b4d73cd3dcfbb17f0605f08cbdf931f96e", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "beef9447e54d63e614c4167a17b565259878e40e654bfa6640662f9f42b9f84a", + "start_line": 12, + "name": "start_link", + "arity": 3 + }, + "child_spec/1:7": { + "line": 7, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 543, + "ast_sha": "fc4089f59098af2b147c7156741d069df101c260a031bdfd9bac6deb22f97153", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "cf6ae509f6d58b1e655f57691748c7c8104d8d68166742572e3d372706e02437", + "start_line": 7, + "name": "child_spec", + "arity": 1 + }, + "render_errors/1:259": { + "line": 259, + "guard": null, + "pattern": "module", + "kind": "defp", + "end_line": 263, + "ast_sha": "e468c0df34c5c5aa7faee547658116da60be151aedc9cc0b4d72651776e65689", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "9a06d14b897730109103c593f2eac9ee038b5dde166bfbf3ac5af7d76a493a02", + "start_line": 259, + "name": "render_errors", + "arity": 1 + }, + "static_lookup/2:292": { + "line": 292, + "guard": null, + "pattern": "_endpoint, <<\"/\"::binary, _::binary>> = path", + "kind": "def", + "end_line": 296, + "ast_sha": "b6ee659363f81693964f01fea47c058449c04c292be284b443ebbc92eb224dea", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "b330c3365be56706750049afd89cfa369d89a0693c2d14aacdd2f9902171c795", + "start_line": 292, + "name": "static_lookup", + "arity": 2 + }, + "port_to_integer/1:315": { + "line": 315, + "guard": "is_integer(port)", + "pattern": "port", + "kind": "defp", + "end_line": 315, + "ast_sha": "3ffa153250cb67eaa24a5ddd12951e20dc5e68138311c00894e86b52593e5fdc", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "074f5f04a25e914d778ae0d21b26d1a362468488bf8979abbc0bab9ad5878c46", + "start_line": 315, + "name": "port_to_integer", + "arity": 1 + }, + "warmup_static/2:429": { + "line": 429, + "guard": null, + "pattern": "_endpoint, _manifest", + "kind": "defp", + "end_line": 430, + "ast_sha": "16da2ddc3c7691a490f0098e6e72db4e76d2336076ca439b0e43d5d404c44b61", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "45e9a118e8349238287cecf6abf38e7a4d7445be2c746e0cbc99291148382112", + "start_line": 429, + "name": "warmup_static", + "arity": 2 + }, + "host_to_binary/1:310": { + "line": 310, + "guard": null, + "pattern": "host", + "kind": "defp", + "end_line": 310, + "ast_sha": "fcc6e42a3178691cc48b853962a3394fe692fb40382672cd3ed333809f8bfc0e", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "5c1f211fed7786a4ce62803ec43b1ba6368132b8316e3013254c6cb6acf4d2dd", + "start_line": 310, + "name": "host_to_binary", + "arity": 1 + }, + "static_lookup/2:300": { + "line": 300, + "guard": "is_binary(path)", + "pattern": "_endpoint, path", + "kind": "def", + "end_line": 301, + "ast_sha": "d837217f8425affa302359b190fbd3b7cc3cafc991fe5fc331a38d153c542d6d", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "1046105d3a9f6b9c2a6572f3c844c6405996fd368fcb1aa994c9f4bc5c76b2e8", + "start_line": 300, + "name": "static_lookup", + "arity": 2 + }, + "port_to_integer/1:313": { + "line": 313, + "guard": null, + "pattern": "{:system, env_var}", + "kind": "defp", + "end_line": 313, + "ast_sha": "d41dcce49c4479fbd0c3c0cbb04ea812c31689deda8e54b4d7647f26fa8e8085", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "e3b91863e72be67bb9de16a0e26ee4de2d7463cc3e0d6b7c8756591f0b7fe557", + "start_line": 313, + "name": "port_to_integer", + "arity": 1 + }, + "apply_or_ignore/3:148": { + "line": 148, + "guard": null, + "pattern": "socket, fun, args", + "kind": "defp", + "end_line": 151, + "ast_sha": "8387c63c772eee2a4405a81495f2acee58f0ba5fd4cdb7abce60b534aeb751e8", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "f78051701607df65a6bf5cc2b768f90055316bacba5dce7cf95fd4772d8eac47", + "start_line": 148, + "name": "apply_or_ignore", + "arity": 3 + }, + "raise_invalid_path/1:304": { + "line": 304, + "guard": null, + "pattern": "path", + "kind": "defp", + "end_line": 305, + "ast_sha": "170fa5d96a379dc770b102d13b6e36ccace2fd2cf3064cc14a7445a177aedc27", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "790af0d8fe7812d232fc7bbcb05c6c5aed8aac6becd26197a9120c75a0bf070c", + "start_line": 304, + "name": "raise_invalid_path", + "arity": 1 + }, + "warmup_persistent/1:368": { + "line": 368, + "guard": null, + "pattern": "endpoint", + "kind": "defp", + "end_line": 387, + "ast_sha": "3538c58c267864f21e396ba8cd90f5df81ea5deb7ae8fa3cd99985e8508ee97e", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "bd8da5a66c77041a8efcc57ebc7fc1bd9dcb9bbcaed65d2933b68e96890197f0", + "start_line": 368, + "name": "warmup_persistent", + "arity": 1 + }, + "static_lookup/2:288": { + "line": 288, + "guard": null, + "pattern": "_endpoint, <<\"//\"::binary, _::binary>> = path", + "kind": "def", + "end_line": 289, + "ast_sha": "03ef91b0ce064d3605432c8b887c1bf2382e4df86d48b08e394dbc82993c79fe", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "4f0c13ae9c95e46fe24a683e71bba6d9cced20472a5f4a46c747ee41d3c15ff7", + "start_line": 288, + "name": "static_lookup", + "arity": 2 + }, + "warmup_static/2:418": { + "line": 418, + "guard": null, + "pattern": "endpoint, %{\"latest\" => latest, \"digests\" => digests}", + "kind": "defp", + "end_line": 424, + "ast_sha": "f3ac4a6430b8618cea5c97593c5ef5d83bc0f30d800727502b6e3d8ee0833f1e", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "502bec3d588803d917e467b880a3817fe8927d095b27d7d1eca1539c10cafdea", + "start_line": 418, + "name": "warmup_static", + "arity": 2 + }, + "watcher_children/3:202": { + "line": 202, + "guard": null, + "pattern": "_mod, conf, server?", + "kind": "defp", + "end_line": 206, + "ast_sha": "c0d43ccbae69b8be02adcfb21651b36c4dd7d6651f680ddf845e0fd884971b32", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "413493f0943ad85e8ce6f68cca0e890876b46b220940c31105a7f1a82720d852", + "start_line": 202, + "name": "watcher_children", + "arity": 3 + }, + "warmup_children/1:178": { + "line": 178, + "guard": null, + "pattern": "mod", + "kind": "defp", + "end_line": 179, + "ast_sha": "f138ec2522d89d76122db38fe6412bcfe0c91ec38fa81a791a421735a1764f22", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "d42942afe03d788797fb32740dd3c0b791f03da6d2cc90da3326dc977a599d74", + "start_line": 178, + "name": "warmup_children", + "arity": 1 + }, + "host_to_binary/1:309": { + "line": 309, + "guard": null, + "pattern": "{:system, env_var}", + "kind": "defp", + "end_line": 309, + "ast_sha": "32e927220b2f9e275dbf1ee80370b484c47df819dc63cc7a801a4d4112c01377", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "06135c36fd39f1fdbe33ca15c51ff20ed357624a256b594b48cdc7b7ab67f9ee", + "start_line": 309, + "name": "host_to_binary", + "arity": 1 + }, + "static_integrity/1:442": { + "line": 442, + "guard": null, + "pattern": "sha", + "kind": "defp", + "end_line": 442, + "ast_sha": "30a9e319d223188f3591de9179478fd88e7358ff26ba12a1c619aa07ff071ab0", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "b6dcd275cf5ef9507c297fba962d07e0d770d41c622e66a8c613ed7ae19a6968", + "start_line": 442, + "name": "static_integrity", + "arity": 1 + }, + "config_change/3:269": { + "line": 269, + "guard": null, + "pattern": "endpoint, changed, removed", + "kind": "def", + "end_line": 272, + "ast_sha": "c9b7d3a94d7e1783eb3e3ab2342c89e248b038e44da5eaec7033431c15f4aeee", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "62b82e1cf5e6450db8082e176cac16a447769ae36adb5b5494483866ec9a6159", + "start_line": 269, + "name": "config_change", + "arity": 3 + }, + "build_url/2:394": { + "line": 394, + "guard": null, + "pattern": "endpoint, url", + "kind": "defp", + "end_line": 415, + "ast_sha": "5286aac7970373d095819d163d3054b8dec510c92097bfa15a562e43ea0df7d0", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "080360e0a41b53b23b8b1e8b2554aeab3dcfb84e96662a0760084931ef106146", + "start_line": 394, + "name": "build_url", + "arity": 2 + }, + "start_link/2:12": { + "line": 12, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 12, + "ast_sha": "cafb953ce5db1f101c82de661d54995c64205e4206978c35644faf2bf3679f49", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "2eeb3b649a27af6def9ae6d4e1b080af5af23fff11ad5cd9a9a81ed2d66ee8f4", + "start_line": 12, + "name": "start_link", + "arity": 2 + }, + "server?/2:215": { + "line": 215, + "guard": "is_atom(otp_app) and is_atom(endpoint)", + "pattern": "otp_app, endpoint", + "kind": "def", + "end_line": 216, + "ast_sha": "502df6aa5eb6c58610c4b46186e72f46b8f4b887b260bc37681845a96bdc4794", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "f59c201163a7b8b32229817761e7d82fdb8029dd85db93ae3117836b1d4c3e4b", + "start_line": 215, + "name": "server?", + "arity": 2 + }, + "static_cache/3:437": { + "line": 437, + "guard": null, + "pattern": "digests, value, false", + "kind": "defp", + "end_line": 438, + "ast_sha": "1ac44d3799accf6bdc5df09932aed0c63ffe4e9450dddf83dba4a72d51d22256", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "7e5f1046566c22663c0ffbc60afdac0b0b5dcefd3e10338b46141e43b9b3fb2a", + "start_line": 437, + "name": "static_cache", + "arity": 3 + }, + "defaults/2:225": { + "line": 225, + "guard": null, + "pattern": "otp_app, module", + "kind": "defp", + "end_line": 232, + "ast_sha": "06ee4eedb27ccbb6be7bd504c68d64364c8910f002224283a9678dc00090b600", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "a9b8d10fa17693c98a426edf3f1b07dde5573001f2f704aa4bf7fdfae680c378", + "start_line": 225, + "name": "defaults", + "arity": 2 + }, + "static_integrity/1:441": { + "line": 441, + "guard": null, + "pattern": "nil", + "kind": "defp", + "end_line": 441, + "ast_sha": "1e9c973a157800df29e20529ffde676e6a5b78f28751532e823d484235666dce", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "8cf25c3cf6b4ae8472af33ff676ad078686637102fe4ea084ebd07eb80c3014b", + "start_line": 441, + "name": "static_integrity", + "arity": 1 + }, + "port_to_integer/1:314": { + "line": 314, + "guard": "is_binary(port)", + "pattern": "port", + "kind": "defp", + "end_line": 314, + "ast_sha": "db5cc62705a108c962a65eed482d322d2c088187c9eac8bca6cb97df4a250d75", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "506fdff094b92b11c5e6bdcbb576f85d8a5503d1d0084c38d965017cec596895", + "start_line": 314, + "name": "port_to_integer", + "arity": 1 + }, + "browser_open/2:474": { + "line": 474, + "guard": null, + "pattern": "endpoint, conf", + "kind": "defp", + "end_line": 485, + "ast_sha": "a1d436e47db6287a78da03438207a4e530892e7c0830eecf0db98ba1d38d6172", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "7aa96161f5da7834d412384a9ab7dc256f1b872eec43d95a3461f2f1c3894acf", + "start_line": 474, + "name": "browser_open", + "arity": 2 + }, + "pubsub_children/2:113": { + "line": 113, + "guard": null, + "pattern": "mod, conf", + "kind": "defp", + "end_line": 133, + "ast_sha": "b457296998162e645e9600c35ecefe495a6ddc400c1fdaeb19ca643fd147f53c", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "9d60f9f76f2c0ac260e2baa793c2aa4ea27b012432cb7141cec283ea37003aaf", + "start_line": 113, + "name": "pubsub_children", + "arity": 2 + }, + "cache_static_manifest/1:444": { + "line": 444, + "guard": null, + "pattern": "endpoint", + "kind": "defp", + "end_line": 459, + "ast_sha": "aa2d56314b10751cac425371741bf0a342f44597e19fbdd94d94a01c54fe1ffa", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "c7ca8b055d7bb6ab93df801f7689bc018e3b227f16342075ea349bd0ff90d4f0", + "start_line": 444, + "name": "cache_static_manifest", + "arity": 1 + }, + "warn_on_deprecated_system_env_tuples/4:317": { + "line": 317, + "guard": null, + "pattern": "otp_app, mod, conf, key", + "kind": "defp", + "end_line": 342, + "ast_sha": "b05d2223b241629c7c7e6ccd43c6a5292b5937e2fd5dd8f3b40d83ab6c4dee68", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "34d01600dd28c18e1c9a23ae145bea7eb869536915572f148df6acd7f3ce60a5", + "start_line": 317, + "name": "warn_on_deprecated_system_env_tuples", + "arity": 4 + }, + "warmup/1:351": { + "line": 351, + "guard": null, + "pattern": "endpoint", + "kind": "def", + "end_line": 359, + "ast_sha": "8724c0a3dddcca8ad3104693e40f396a43bdbd59b06b460896d3e17ec6ea2582", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "129fe72477fbab12f3a0c24a7cbdde88c0dd99e4776c2f882e05b54c9bdd1540", + "start_line": 351, + "name": "warmup", + "arity": 1 + }, + "log_access_url/2:468": { + "line": 468, + "guard": null, + "pattern": "endpoint, conf", + "kind": "defp", + "end_line": 470, + "ast_sha": "db66bf9eded7009d32855105e0067e90e97b33fb88531022ddcb4a46f788a515", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "219b723eb9339535548704c48349be7fff45d2b3b3bd1d5663267dfb68c94d56", + "start_line": 468, + "name": "log_access_url", + "arity": 2 + }, + "socket_children/3:139": { + "line": 139, + "guard": null, + "pattern": "endpoint, conf, fun", + "kind": "defp", + "end_line": 144, + "ast_sha": "07d4b51c8cb8b3c3aa17448031c0653be87350ab8149f1d667a8a1932bdecf0b", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "861df0fa8d3cec1eadc502e5d2b1a429159415765c0293736b28fbf81892a44a", + "start_line": 139, + "name": "socket_children", + "arity": 3 + }, + "check_origin_or_csrf_checked!/2:157": { + "line": 157, + "guard": null, + "pattern": "endpoint_conf, socket_opts", + "kind": "defp", + "end_line": 168, + "ast_sha": "409b994f86f1b81ab8c3a363ebf2a0c5243edadd04c61cbd813c4e2b5bdf1cc8", + "source_file": "lib/phoenix/endpoint/supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", + "source_sha": "d2d1ae88bcbcb46c851fb7929f6e6cee88858ca02d9fb26778271e9d03602cb1", + "start_line": 157, + "name": "check_origin_or_csrf_checked!", + "arity": 2 + } + }, + "Mix.Tasks.Phx.Gen.Secret": { + "invalid_args!/0:33": { + "line": 33, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 34, + "ast_sha": "ac8aba55bc9e914764ee7241f4e0726d3ba526af43804596ebee7be7142f1ab4", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "97ebfe76dd462d0119acdf9198aef34ccd51fbb721c21fb6c0451a854791f1b0", + "start_line": 33, + "name": "invalid_args!", + "arity": 0 + }, + "parse!/1:20": { + "line": 20, + "guard": null, + "pattern": "int", + "kind": "defp", + "end_line": 23, + "ast_sha": "7f6970802a324c0733e6fbb0a42e5a908e7247a8b7e9695668eb43b5d578bf65", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "6d7b111826cc6b57d9b404144026fd3a96a1f1bc9cb9ce25c2088578d21f0307", + "start_line": 20, + "name": "parse!", + "arity": 1 + }, + "random_string/1:27": { + "line": 27, + "guard": "length > 31", + "pattern": "length", + "kind": "defp", + "end_line": 28, + "ast_sha": "7f587bd97fa01da6cc93c79851d3440ed7320e1423bc2d233330ad6f5050bdd4", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "4747f00851adcea08c0bcea8fe34c0f4dce6a9c59870ab93dbda2ba70cc61116", + "start_line": 27, + "name": "random_string", + "arity": 1 + }, + "random_string/1:30": { + "line": 30, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 30, + "ast_sha": "3cf69dd38986280d271ca211a07635d4e05f8a4b822b01ab284c21281c26e5f2", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "3a4cf7c9e46b8a2b06cde069d53bd23f1a7bf4c73de45c56882c9e861f2817e4", + "start_line": 30, + "name": "random_string", + "arity": 1 + }, + "run/1:16": { + "line": 16, + "guard": null, + "pattern": "[]", + "kind": "def", + "end_line": 16, + "ast_sha": "495e019cfb92b9acc9d4f44c90eb6cd719ac2c2a7cd9ecd724a2d55fd3bca279", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "03576cd8aa7daf37637d7867f227f561c1d7730a51f3eef36aaa59b47fcd757e", + "start_line": 16, + "name": "run", + "arity": 1 + }, + "run/1:17": { + "line": 17, + "guard": null, + "pattern": "[int]", + "kind": "def", + "end_line": 17, + "ast_sha": "7e6051eb3353159488a18104b4eb1ca0bd54c05a578b246cef8bcc5dc5c0f944", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "910cf0ba6c184979bddeaddfd3f04a0cf8da11114420e939fcf991b96ac397c4", + "start_line": 17, + "name": "run", + "arity": 1 + }, + "run/1:18": { + "line": 18, + "guard": null, + "pattern": "[_ | _]", + "kind": "def", + "end_line": 18, + "ast_sha": "b315480f7c5d7bf47260f7b801aaf676e0f89c258aae37ef882376b4caad3944", + "source_file": "lib/mix/tasks/phx.gen.secret.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", + "source_sha": "71fc1519ff0da8256aeee0cd62bb861acecb594a0449f2d50da02ac79941905a", + "start_line": 18, + "name": "run", + "arity": 1 + } + }, + "Phoenix.ChannelTest.NoopSerializer": { + "decode!/2:173": { + "line": 173, + "guard": null, + "pattern": "message, _opts", + "kind": "def", + "end_line": 173, + "ast_sha": "c04be04cb42c8dde80aa7b1351a0bdd519e2ff03c6a8c368d6ebdeee74d62b48", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "6b5aba4a6a344baa3f8ab7fdd8a907554f8f9c95b4ea9113f6b7353bd9cda0bf", + "start_line": 173, + "name": "decode!", + "arity": 2 + }, + "encode!/1:171": { + "line": 171, + "guard": null, + "pattern": "%Phoenix.Socket.Reply{} = reply", + "kind": "def", + "end_line": 171, + "ast_sha": "bcf140b2e6029e5d5531cb15c50ff21aaf083b28b71e7443b9a8394463dcbe3f", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "5b9c14cb002e13aaa461f8453e2cfe9dbe92583242d50c72f696debac3f6f4c8", + "start_line": 171, + "name": "encode!", + "arity": 1 + }, + "encode!/1:172": { + "line": 172, + "guard": null, + "pattern": "%Phoenix.Socket.Message{} = msg", + "kind": "def", + "end_line": 172, + "ast_sha": "94dd986ef05fd6506424136c448f8ee7a15bea7343eca32137d127aa76c76c12", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "656caac21aa344c37d1abac6a3b27731a8d32efe3b0aa1f82c43904298dd5867", + "start_line": 172, + "name": "encode!", + "arity": 1 + }, + "fastlane!/1:163": { + "line": 163, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{} = msg", + "kind": "def", + "end_line": 167, + "ast_sha": "c199eb4850cd53b34b1bd8c438207dddd91fff386f2ba5473f14bc100243d9fd", + "source_file": "lib/phoenix/test/channel_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", + "source_sha": "846e6c32cd882ab865aaf0b5635ba409532d21fb203ce714fecc5ac954577365", + "start_line": 163, + "name": "fastlane!", + "arity": 1 + } + }, + "Phoenix.Router": { + "post/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "0e59357ddfef3bee1af4b07cff8c5efb5148b24be8f28fa9cde9c51612cd22b1", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "post", + "arity": 4 + }, + "scope/3:1097": { + "line": 1097, + "guard": null, + "pattern": "path, options, [do: context]", + "kind": "defmacro", + "end_line": 1115, + "ast_sha": "90a8f20a2c840737ee1a7cfe2e15ffef3019c2b17a8cbbeb16e39dd88fafd299", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "7af90d3810d149dd7d468616923fb329100817f9215f851ec6bd41239fecf01d", + "start_line": 1097, + "name": "scope", + "arity": 3 + }, + "scope/2:1070": { + "line": 1070, + "guard": null, + "pattern": "options, [do: context]", + "kind": "defmacro", + "end_line": 1078, + "ast_sha": "99a29b86a629491a2bcd8cb781cef988813e30f189c3dec4177cb9c509854a9f", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "43d3e2d03c37268853933ec41af0bf6cb4519af302304bd2828169304c005f54", + "start_line": 1070, + "name": "scope", + "arity": 2 + }, + "plug/1:828": { + "line": 828, + "guard": null, + "pattern": "x0", + "kind": "defmacro", + "end_line": 828, + "ast_sha": "aad9102eb389ee539b38e9dd07453ea6d271b2a04434d05298a15f0a6be17bd7", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "566f97ce1b8ef8b2037a65501fd516896ef4887adb316b93b0fff31fe1a371da", + "start_line": 828, + "name": "plug", + "arity": 1 + }, + "trace/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "12298e8c5cd6e0a43386bc4e650c01ff9340923edc3ee4e473da56429f80e25f", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "trace", + "arity": 4 + }, + "__call__/5:396": { + "line": 396, + "guard": null, + "pattern": "%{private: %{phoenix_bypass: :all}} = conn, metadata, prepare, _, _", + "kind": "def", + "end_line": 397, + "ast_sha": "41db49b45ed67e0a35a1c8cbe0cfb6d614cf8b5166b8ec2fe1f712db3df10c4f", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "04acb2eb559f6ff70601d3ffdbd632d3e14439f0ea44a8196b6b45897a1ba1a7", + "start_line": 396, + "name": "__call__", + "arity": 5 + }, + "__before_compile__/1:488": { + "line": 488, + "guard": null, + "pattern": "env", + "kind": "defmacro", + "end_line": 564, + "ast_sha": "02f546bead18749ba91e0a5057127e9ee632cdff587461187719f6b21ca539ca", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "656b4ae42ae7691f7f03df1e9e511b06b4d2c7cf940b680e1453a378aef328f3", + "start_line": 488, + "name": "__before_compile__", + "arity": 1 + }, + "routes/1:1228": { + "line": 1228, + "guard": null, + "pattern": "router", + "kind": "def", + "end_line": 1229, + "ast_sha": "d8b092fd3517df646a8c17cd97e97de4cf65d11d6ebed356772e43956ab8f13c", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "e5a61fd4fc4c829d5f12b98765a89c4efcc86c980dd045f300a4ad665abb1a97", + "start_line": 1228, + "name": "routes", + "arity": 1 + }, + "resources/2:1017": { + "line": 1017, + "guard": null, + "pattern": "path, controller", + "kind": "defmacro", + "end_line": 1018, + "ast_sha": "539036293a43b8e08d6b6e67496e80adf789ab5d02c081dfe805bb22baee0898", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "bc61f3f2f0534f5306816bb3d5b1bdb7547ad26134734ffdf5554258b9cd8eec", + "start_line": 1017, + "name": "resources", + "arity": 2 + }, + "forward/3:1216": { + "line": 1216, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 1216, + "ast_sha": "e347a86279e393b879e18977a0e7f95fb8676e8c191fe59d6ff3fee99c630244", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "eda0d06da0bb3c8f94779d1aac43923954ce797908365238c6dc2cd1f19014e2", + "start_line": 1216, + "name": "forward", + "arity": 3 + }, + "add_route/6:738": { + "line": 738, + "guard": null, + "pattern": "kind, verb, path, plug, plug_opts, options", + "kind": "defp", + "end_line": 748, + "ast_sha": "f37d0b447e8c5393ebaa90052a568382d2065b8742de1d047cf996754b86367f", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "19080d062522e17be12a0123d40d99e29633f8ad4a5daa7e0597282541709114", + "start_line": 738, + "name": "add_route", + "arity": 6 + }, + "resources/4:999": { + "line": 999, + "guard": null, + "pattern": "path, controller, opts, [do: nested_context]", + "kind": "defmacro", + "end_line": 1000, + "ast_sha": "15889f6f0dde38d0180ae4f6b066a145364b4748b2c45b1451dcccfb057dab82", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "d39fcf025da183dfb36b610bf35885b9211dc3557c998b87846c25aef3c2de00", + "start_line": 999, + "name": "resources", + "arity": 4 + }, + "build_verify/2:568": { + "line": 568, + "guard": null, + "pattern": "path, routes_per_path", + "kind": "defp", + "end_line": 588, + "ast_sha": "d7025feb4794c3a853371e6059b72e1cac9f41cb64dbbcd13730e9edf88c81b1", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "f4ce920d62822de96267c68c5f4ada99b25aa130e13f57cc679b7c80e46cb10a", + "start_line": 568, + "name": "build_verify", + "arity": 2 + }, + "__call__/5:400": { + "line": 400, + "guard": null, + "pattern": "conn, metadata, prepare, pipeline, {plug, opts}", + "kind": "def", + "end_line": 436, + "ast_sha": "30ecba9dcac699093141e68f7bccf015d08a6a997345bcca0c0600289a648ff3", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "6a5c1bb0425a57b2275e12851e65dffd0365d55600c3bac408e27da030f95167", + "start_line": 400, + "name": "__call__", + "arity": 5 + }, + "connect/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "63beb90ed591a4a2fd57a166458013161ee8b716528af99896c6bcd2fd0350c8", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "connect", + "arity": 3 + }, + "scoped_path/2:1180": { + "line": 1180, + "guard": null, + "pattern": "router_module, path", + "kind": "def", + "end_line": 1181, + "ast_sha": "06d1585a620ed35a0c4c558063c112db2c9d4d080524a309cc93a8485cda0659", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "10d0232a55851fbc85e5ed7af5228391e67c5cf8e3d07b0dc509200514878bca", + "start_line": 1180, + "name": "scoped_path", + "arity": 2 + }, + "build_pipes/2:663": { + "line": 663, + "guard": null, + "pattern": "name, pipe_through", + "kind": "defp", + "end_line": 669, + "ast_sha": "4dc13add9e8dbd23917fc0e8d76da71ab7df789f9c99e56ee5dc2f21a71daf06", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "ff662dcd1d075ca73261a1cc5450b4eb80ef5c672ad1e813a0ce92d5acd2fee0", + "start_line": 663, + "name": "build_pipes", + "arity": 2 + }, + "resources/3:1010": { + "line": 1010, + "guard": null, + "pattern": "path, controller, opts", + "kind": "defmacro", + "end_line": 1011, + "ast_sha": "671cc4600d56780ef93c788ea5627473f2a346ac34e4ea3d550c0c0f1d6ce609", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "8c401acd4d34ad091fd1932c3ddb943de3d77d12ba159c2ecd57607f63f0407b", + "start_line": 1010, + "name": "resources", + "arity": 3 + }, + "resources/3:1006": { + "line": 1006, + "guard": null, + "pattern": "path, controller, [do: nested_context]", + "kind": "defmacro", + "end_line": 1007, + "ast_sha": "5f55b59bd97696521707c9b2ec937edf7ad197a95ab3c660835f034433ba46c6", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "3435ca2a8ddca26cde9364ebcfe11e29709e022b6e51cfa8e338ceb16133028b", + "start_line": 1006, + "name": "resources", + "arity": 3 + }, + "pipeline/2:775": { + "line": 775, + "guard": null, + "pattern": "plug, [do: block]", + "kind": "defmacro", + "end_line": 816, + "ast_sha": "e4a183610dfd5e8868a2c452368d6eecb87107ae982686f177f65a6d457a9c76", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "2868a27400e0532f7af6ddb375179f585884958088978def4fdc9a955a3a6456", + "start_line": 775, + "name": "pipeline", + "arity": 2 + }, + "head/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "6b3d8695486de354938c49d36e5334ae25ce2600fe94a0216b7b4d6d0c8ed76b", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "head", + "arity": 4 + }, + "__verified_route__?/2:1313": { + "line": 1313, + "guard": null, + "pattern": "router, split_path", + "kind": "def", + "end_line": 1330, + "ast_sha": "db16dce3ecdf3a77dab51fbfcec7045a74edbbd9d69bc4404fdcb2f42de5dd8d", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "0eb070c41ed5597253bbe12ad7e0d905aac1c75ada3472e031cfe39b5baace62", + "start_line": 1313, + "name": "__verified_route__?", + "arity": 2 + }, + "prelude/1:297": { + "line": 297, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 312, + "ast_sha": "567715972e028612db0468f69f056f7be090320aaa585d5c28596d110eb2c134", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "418fd5a5f9a0bcb6a2ecf09b44820c3acd827110d897ef6151a2591250ffd2f9", + "start_line": 297, + "name": "prelude", + "arity": 1 + }, + "match_dispatch/0:441": { + "line": 441, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 441, + "ast_sha": "2e49f3567fbca82331c87402df68cedbaca54e8a2c351461d76958f4ad07f38e", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "8af58e20d8a2b4fe1d24c0bc1b7c6340f857d99c8c19080215c964951999bae2", + "start_line": 441, + "name": "match_dispatch", + "arity": 0 + }, + "patch/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "8f47cf5e3d667575fa1ef6ad651966c3fb79aa99948e64c73d9a8e5b86d2ae60", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "patch", + "arity": 4 + }, + "match/5:709": { + "line": 709, + "guard": null, + "pattern": "verb, path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 710, + "ast_sha": "ad85657425e03ff6f7282d434473bb9b458fae5f18184b54c776bbfaeff34033", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "56330fd4896917ae74d8df1173fd2205385574d2b69bb64e9a3ac75a0247c396", + "start_line": 709, + "name": "match", + "arity": 5 + }, + "options/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "dc6c0db4158027e638811a79a8ae2373ea9b7b54f154fdd3a1072b4d3b51ef1a", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "options", + "arity": 3 + }, + "get/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "c119cdc66c1e8fae8d571d1db11bd1f6c8c99822487997cafb37c79e7036848e", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "get", + "arity": 3 + }, + "match/4:709": { + "line": 709, + "guard": null, + "pattern": "x0, x1, x2, x3", + "kind": "defmacro", + "end_line": 709, + "ast_sha": "48ab80f9a30dbe4d63edd8f44195e742cb78f74eb5e9ad5c688c5bc7fb0ad5aa", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "af0f2afea612f74694623d64e359d0129d5fab6a8fbd7fac5e73a3281e47d3b4", + "start_line": 709, + "name": "match", + "arity": 4 + }, + "build_match_pipes/3:621": { + "line": 621, + "guard": null, + "pattern": "route, acc_pipes, known_pipes", + "kind": "defp", + "end_line": 632, + "ast_sha": "5f6853c8f6e8688590efc171c1d66498007127985788b6eb2eeb9de5693cd608", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "a9380e8e7763795ddbf9c6dd28b81806f79f22254dd111df3f3812fee7043909", + "start_line": 621, + "name": "build_match_pipes", + "arity": 3 + }, + "__using__/1:288": { + "line": 288, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 293, + "ast_sha": "c8d90b225bc1a3c07bcf9d22f805a31d2b451249a717df2cd623a4a973685192", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "f03024267e0919734b75c89c96d08ec575c5ec621dd46381db7c5a5ff1778adf", + "start_line": 288, + "name": "__using__", + "arity": 1 + }, + "forward/4:1216": { + "line": 1216, + "guard": null, + "pattern": "path, plug, plug_opts, router_opts", + "kind": "defmacro", + "end_line": 1221, + "ast_sha": "6008ad8a4dfd883d4d75e954b59940458eaf88ced4fd7611807fb9a880d61ed0", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "489de9848694acaab0edce86512f8d746c9dca765e6f8a1341be827396bb9ae5", + "start_line": 1216, + "name": "forward", + "arity": 4 + }, + "build_match/2:594": { + "line": 594, + "guard": null, + "pattern": "{route, expr}, {acc_pipes, known_pipes}", + "kind": "defp", + "end_line": 618, + "ast_sha": "cdaf15f1397eba1ec399c29156993322a652331a22429fd3d1bd4732fc3e2eca", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "e04f778801f7a06b25629f120b84ee74de8c3b97c0c069124e8953eb50a0b4f6", + "start_line": 594, + "name": "build_match", + "arity": 2 + }, + "do_scope/2:1147": { + "line": 1147, + "guard": null, + "pattern": "options, context", + "kind": "defp", + "end_line": 1152, + "ast_sha": "af9888494e03c1dc61ac8694080388705911e13f625049205ab3f1d0ec7bd668", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "877433aad2e1ee6e5e394d45a321905dc33e9394165826f622ffdc1e999925a0", + "start_line": 1147, + "name": "do_scope", + "arity": 2 + }, + "options/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "e15cff8d08202b5882f84dcf43f1b894d9781215f166aa622cf0021e7ebe5f05", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "options", + "arity": 4 + }, + "patch/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "45b9a1b7c3e9e831b553b86176e4993adf206572a6dc07408db61e5ab455e4c1", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "patch", + "arity": 3 + }, + "pipe_through/1:904": { + "line": 904, + "guard": null, + "pattern": "pipes", + "kind": "defmacro", + "end_line": 916, + "ast_sha": "871c6453dafd4c5bc4f0bb6a6083d6271911e3597eaca2e4006ad780ed9989d5", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "eda3b8fecb8801039e6e766e0c5c5dafcc55b885d826df583ee95efdc00e200a", + "start_line": 904, + "name": "pipe_through", + "arity": 1 + }, + "connect/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "e2f4a8a2e485da18f1be3f6862242c7e562740c53e6db6d784ea8e6ebabb905e", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "connect", + "arity": 4 + }, + "route_info/4:1267": { + "line": 1267, + "guard": "is_list(split_path)", + "pattern": "router, method, split_path, host", + "kind": "def", + "end_line": 1270, + "ast_sha": "19aa0324df8adce38477aa59ae4d172fe88ff3ab3b1b7098b010659c59f64189", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "a1202624790a76e5edaf304dba7f3994c68c895ae5552ed59cd0c549d17fe38b", + "start_line": 1267, + "name": "route_info", + "arity": 4 + }, + "expand_alias/2:863": { + "line": 863, + "guard": null, + "pattern": "other, _env", + "kind": "defp", + "end_line": 863, + "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", + "start_line": 863, + "name": "expand_alias", + "arity": 2 + }, + "defs/0:321": { + "line": 321, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 321, + "ast_sha": "8fd9a259c1471681b8fffb18681ddb569d151e7f8028e239c8befbb4984c2d01", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "0e059e9f76e9129199db5ba3543a3e66c7f1c9859ea82283efee6d093e976015", + "start_line": 321, + "name": "defs", + "arity": 0 + }, + "head/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "1f90ac08eeeb4fda484f76ab0a2e652765e4ce796ca72087c7dead7d68e32d11", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "head", + "arity": 3 + }, + "scoped_alias/2:1172": { + "line": 1172, + "guard": null, + "pattern": "router_module, alias", + "kind": "def", + "end_line": 1173, + "ast_sha": "4cc94f133766c4cb8192fed33bfc0290f442e0060cf8e7196e42d288efcf21d0", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "decd30169223f82e090eaa8f2eb2b7f7c9a15eb3146e5cc744cf823e150a4d03", + "start_line": 1172, + "name": "scoped_alias", + "arity": 2 + }, + "__formatted_routes__/1:1275": { + "line": 1275, + "guard": null, + "pattern": "router", + "kind": "def", + "end_line": 1305, + "ast_sha": "02abe097d03394bb882beea218e6452e84a3a3c4cbacc297267e20c014c654fa", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "32bc69459a6918576cca274a6e152fb21074f5ccafa61d58ec7957e30b76f44d", + "start_line": 1275, + "name": "__formatted_routes__", + "arity": 1 + }, + "__call__/5:381": { + "line": 381, + "guard": null, + "pattern": "%{private: %{phoenix_router: router, phoenix_bypass: {router, pipes}}} = conn, metadata, prepare, pipeline, _", + "kind": "def", + "end_line": 392, + "ast_sha": "44a9a06e13fa376194f571748f6794119093fa9262d86407711994b41331eab9", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "ddf8f4cb5ba0e5fe76669cbdf84326d9e39aad9c263bf1db70df94d680565fb5", + "start_line": 381, + "name": "__call__", + "arity": 5 + }, + "forward/2:1216": { + "line": 1216, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 1216, + "ast_sha": "d9dc0ea4147bc9c29b31d5a205a6ff27435da4fbea45cc9f3e0134339fc7a868", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "eda0d06da0bb3c8f94779d1aac43923954ce797908365238c6dc2cd1f19014e2", + "start_line": 1216, + "name": "forward", + "arity": 2 + }, + "build_metadata/2:636": { + "line": 636, + "guard": null, + "pattern": "route, path_params", + "kind": "defp", + "end_line": 654, + "ast_sha": "12094b7ee8dc4d746ad08e6ed26bd8f6c8436284336b235ac9e80541c6778f2c", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5cdccf27498f6af6785017b71e11aa240549643dd5992cad0a3d7467564328b9", + "start_line": 636, + "name": "build_metadata", + "arity": 2 + }, + "build_pipes/2:657": { + "line": 657, + "guard": null, + "pattern": "name, []", + "kind": "defp", + "end_line": 659, + "ast_sha": "27734ae7a8cfefb15a381a31eb315884d5f42d41f2fb123c16f95df5ab2687da", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "fa9633370095bd51fcab5db0bf4acc781e3afa1b904b87a43e88a673a603684f", + "start_line": 657, + "name": "build_pipes", + "arity": 2 + }, + "put/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "793ee208cdfb684424223eef5215d939c8bbaedfd9941bf4a46c75a7fdb94b61", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "put", + "arity": 3 + }, + "scope/4:1134": { + "line": 1134, + "guard": null, + "pattern": "path, alias, options, [do: context]", + "kind": "defmacro", + "end_line": 1144, + "ast_sha": "a078685fb8d216c1151cb1381db8b0513ebeb3e7eb2a8db4f69a8b72affb9ae8", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b3aeb41f56d10c83a9741400dc1eb8149b02f145546a2235161868316944e19e", + "start_line": 1134, + "name": "scope", + "arity": 4 + }, + "delete/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "96daae441d73ab81840590d74e2d8d764ebb1f6ee44d8cb31f0c90bf7459f27e", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "delete", + "arity": 3 + }, + "delete/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "c6989613a8d8fc6d604c07cefe03d6c0a7652849dfdb8ab39fe79eab3797d6c8", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "delete", + "arity": 4 + }, + "post/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "bb29c814b47c408571b7bf34756e385f0c1bf19f9255d0f07beead88807ff5bd", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "post", + "arity": 3 + }, + "plug/2:828": { + "line": 828, + "guard": null, + "pattern": "plug, opts", + "kind": "defmacro", + "end_line": 833, + "ast_sha": "932432518ae3fd6cbe76b3729fc1f3da26a56fb30221fca41072445142546d72", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "7d11be1b0c1cc1b5f3e9ca223db9a94d4448b0264ce945c5eaa50a38845842dc", + "start_line": 828, + "name": "plug", + "arity": 2 + }, + "put/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "771a9c5d991934aef109efde260b72158a6bc1b6d1faa34eb3dedfb7ed38309e", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "put", + "arity": 4 + }, + "add_resources/4:1021": { + "line": 1021, + "guard": null, + "pattern": "path, controller, options, [do: context]", + "kind": "defp", + "end_line": 1032, + "ast_sha": "17bfabd0cb71ebcf3beb99e755355bc76837d051be063630554628aced425859", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "a1978a19f713f08475b71fd30d67cc620d8230fdcc2299146bbd333e21c6f237", + "start_line": 1021, + "name": "add_resources", + "arity": 4 + }, + "route_info/4:1262": { + "line": 1262, + "guard": "is_binary(path)", + "pattern": "router, method, path, host", + "kind": "def", + "end_line": 1264, + "ast_sha": "6050107ba2e4ee748082220b0769a949c1c0dce7938e7b022457aee60107b1fe", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "741b5dade1d62f14dfd3dd2e08404483d7735eb2d6669050906a0dc8d4618886", + "start_line": 1262, + "name": "route_info", + "arity": 4 + }, + "trace/3:733": { + "line": 733, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "defmacro", + "end_line": 733, + "ast_sha": "456c0d1abd1c3e52172dc61c32975caaa24b00296b38400d1833c01acf6235a2", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", + "start_line": 733, + "name": "trace", + "arity": 3 + }, + "verified_routes/0:473": { + "line": 473, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 473, + "ast_sha": "01a8c10409f41cf04c0e5e17278c1cdae122fe467851bbd79a30ed3ab02ad11d", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "ebfa1c9a879954efb1053fa49256efd4a0bc9e66c00088eafc5de0b0d1472957", + "start_line": 473, + "name": "verified_routes", + "arity": 0 + }, + "expand_plug_and_opts/3:840": { + "line": 840, + "guard": null, + "pattern": "plug, opts, caller", + "kind": "defp", + "end_line": 857, + "ast_sha": "224161e0d9cdeb5e03c50f38a93fc5f10147c1ddfae30b2c417f570b9d04fe60", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "f884150199adfbde9bb78fa43eb68bd2365cc9b2e8255c1bf2093a0aebb4f2c6", + "start_line": 840, + "name": "expand_plug_and_opts", + "arity": 3 + }, + "expand_alias/2:860": { + "line": 860, + "guard": null, + "pattern": "{:__aliases__, _, _} = alias, env", + "kind": "defp", + "end_line": 861, + "ast_sha": "46825d111bdb687c2946a41c5f062a2befb82c3f7b34afbd7463d35cc50a03b9", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "7599dd70b9a94c532aa4050ea2895b5b7ceb706318007c89ad50955b47a88598", + "start_line": 860, + "name": "expand_alias", + "arity": 2 + }, + "get/4:733": { + "line": 733, + "guard": null, + "pattern": "path, plug, plug_opts, options", + "kind": "defmacro", + "end_line": 734, + "ast_sha": "45216270138815a3ab2be8c3441d2bb94d614014221b153f8a90c9a42aa1064f", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", + "start_line": 733, + "name": "get", + "arity": 4 + } + }, + "Phoenix.Presence": { + "__using__/1:367": { + "line": 367, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 368, + "ast_sha": "68967b139efedb77a4a6e280b8ea91befc6387a7c4109a564bd716057f91b011", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "f9c991da4efc6d6649e630a79d60f91ea5f8928cae07fc4c94e075c1466407ee", + "start_line": 367, + "name": "__using__", + "arity": 1 + }, + "add_new_presence_or_metas/4:676": { + "line": 676, + "guard": null, + "pattern": "topics, topic, key, new_metas", + "kind": "defp", + "end_line": 697, + "ast_sha": "67e24b010f5000165c9a546959901fa6fe9a77f4dab6dae603f6945b605bc4ed", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "858c280e0ac7dd54e1379471de3ecfb60d64403426dab9655157c7d0a7bfb46a", + "start_line": 676, + "name": "add_new_presence_or_metas", + "arity": 4 + }, + "add_new_topic/2:719": { + "line": 719, + "guard": null, + "pattern": "topics, topic", + "kind": "defp", + "end_line": 720, + "ast_sha": "e3d81a2226d4e9c619eadabdeb9a2f3c76f225d43b796324e4b5d83ba4bf5d0c", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "c7f5ccd5786fad8e008fe755d885230c618138bba90a2d757fc81e61b7cf628b", + "start_line": 719, + "name": "add_new_topic", + "arity": 2 + }, + "async_merge/2:620": { + "line": 620, + "guard": null, + "pattern": "state, diff", + "kind": "defp", + "end_line": 642, + "ast_sha": "d7f30286c81622d5ce5e05e4aae4c13d5677c6c4a19fcabcc4805dbcc2aa5631", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "ba2d407f79ea12a0e0383d79d5796c25ac79d4a296c02dfe5d75b8b963024880", + "start_line": 620, + "name": "async_merge", + "arity": 2 + }, + "do_handle_metas/2:596": { + "line": 596, + "guard": null, + "pattern": "state, computed_diffs", + "kind": "defp", + "end_line": 614, + "ast_sha": "727e59ea71dbddf424d5b274441ea3b4901f3bf0a6321bb6f0860f0c03289044", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "bc7edfca8dbe0cbb2b33d2bb1895a1d9907e667041e6c1a2c2c6c8f22fa48e6c", + "start_line": 596, + "name": "do_handle_metas", + "arity": 2 + }, + "get_by_key/3:558": { + "line": 558, + "guard": null, + "pattern": "module, topic, key", + "kind": "def", + "end_line": 568, + "ast_sha": "c1d62984e94150213c2227b1eb3b5d81e1dbc7a956d5f956b0e319355204ab0e", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "d7f2076ff9d9031e91e9a80b95da5e9f202378cbc35803fb8d0226412b590471", + "start_line": 558, + "name": "get_by_key", + "arity": 3 + }, + "group/1:573": { + "line": 573, + "guard": null, + "pattern": "presences", + "kind": "def", + "end_line": 578, + "ast_sha": "0af4b582f7ec7eb09b9f7423f181c0026cd817dc550c7e557bce76b707fd2908", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "74a6331ec89817d4d49cad983ce4bc08de7b8e8835386fa6191c4eba0da95356", + "start_line": 573, + "name": "group", + "arity": 1 + }, + "handle_diff/2:517": { + "line": 517, + "guard": null, + "pattern": "diff, state", + "kind": "def", + "end_line": 518, + "ast_sha": "6fc3a384b54fee2b155900f84774687638bfa879259d9d6b490902da3b20d439", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "9c2c5984b7aac245d62a769cb4f2a03079edf1e45b7667dc4b79102dc8a2d427", + "start_line": 517, + "name": "handle_diff", + "arity": 2 + }, + "handle_info/2:522": { + "line": 522, + "guard": null, + "pattern": "{task_ref, {:phoenix, ref, computed_diffs}}, state", + "kind": "def", + "end_line": 544, + "ast_sha": "2bcc7b4cb5a4479539b4b97ce1ac175205b61270b0142000560ae74166470398", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "b7a9d5ccc3b4ef044363dec2c5229cae0bd633ea56ba63d555cc64df901c90f0", + "start_line": 522, + "name": "handle_info", + "arity": 2 + }, + "handle_join/2:667": { + "line": 667, + "guard": null, + "pattern": "{joined_key, presence}, {topics, topic}", + "kind": "defp", + "end_line": 669, + "ast_sha": "18fdd7fb0f45fc3dc948bce0ffd272d299fc6e7e36943ded19bb0ddf22cd6cfb", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "439d2622e5ef301f087172a571319c0f7b0c50dc4703aac44e67caf2bd2c28bb", + "start_line": 667, + "name": "handle_join", + "arity": 2 + }, + "handle_leave/2:672": { + "line": 672, + "guard": null, + "pattern": "{left_key, presence}, {topics, topic}", + "kind": "defp", + "end_line": 673, + "ast_sha": "faf50a907ca6f44674ddae7ca53337ed57e9afed91efedcc44942cae12c1d557", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "09163f4b74e47036747219774a5d2da7b747113c098466de37d23e9fc03a1159", + "start_line": 672, + "name": "handle_leave", + "arity": 2 + }, + "init/1:475": { + "line": 475, + "guard": null, + "pattern": "{module, task_supervisor, pubsub_server, dispatcher}", + "kind": "def", + "end_line": 513, + "ast_sha": "dcce1b603ad2fa4c80edad6e9c9ff348e70132e611300ecaedb8ff4584acb7e1", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "b2f0301b8309f11558d76110b2fd085c8c8c4ddba8e4c815c02a8a7f6c2e8bef", + "start_line": 475, + "name": "init", + "arity": 1 + }, + "list/2:548": { + "line": 548, + "guard": null, + "pattern": "module, topic", + "kind": "def", + "end_line": 554, + "ast_sha": "bda1768f58d85f2b7ffd3722698d69acd9808b5b246bcdaaf7317272b79f2abf", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "42eda95dc58894a5da68ef7b5c22ddd61d8bde002fc8cbd6aa2405862a39afc0", + "start_line": 548, + "name": "list", + "arity": 2 + }, + "merge_diff/3:646": { + "line": 646, + "guard": null, + "pattern": "topics, topic, %{leaves: leaves, joins: joins} = _diff", + "kind": "defp", + "end_line": 663, + "ast_sha": "ccd1e2c9ee9d970670216e750bfdb2f18fc54711a6c158238c299bbb1a98e384", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "5b3d6e18c5c1f3f4b07e5efb1ec97d1f6e7a4ff005495d3003c8480d9054ee0f", + "start_line": 646, + "name": "merge_diff", + "arity": 3 + }, + "next_task/1:585": { + "line": 585, + "guard": null, + "pattern": "state", + "kind": "defp", + "end_line": 592, + "ast_sha": "e60d21c1a90cc17328c2389a21ed765ec60cbad6fb361cd4949342ea6bbd8bf0", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "5f84268267993b17d25b5d768bf5d70cf65fee33c3dd3ff762a55cdd255be6d9", + "start_line": 585, + "name": "next_task", + "arity": 1 + }, + "remove_presence_or_metas/4:700": { + "line": 700, + "guard": null, + "pattern": "topics, topic, key, deleted_metas", + "kind": "defp", + "end_line": 716, + "ast_sha": "3bcce89dc05e47afdf87c4b62019a9879cce233521bc793ece7fd7b6e3accba4", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "0a90d0dcaff699aff40eed24fe962f8210ab44d08c3eb9c1e196dc20c012c8cb", + "start_line": 700, + "name": "remove_presence_or_metas", + "arity": 4 + }, + "remove_topic/2:723": { + "line": 723, + "guard": null, + "pattern": "topics, topic", + "kind": "defp", + "end_line": 724, + "ast_sha": "af79d54349780ca8063a05a4770b03dc4ced380d9249a9262921865c174a0d28", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "ad4be2fa8d68ff72ee7de96679d1debcf479c96c1cd2a8691057ccf12b0a6987", + "start_line": 723, + "name": "remove_topic", + "arity": 2 + }, + "send_continue/2:583": { + "line": 583, + "guard": null, + "pattern": "%Task{} = task, ref", + "kind": "defp", + "end_line": 583, + "ast_sha": "db5713f74b8bb8c6248c7f306f8f023ddf80604f05a0a539eb5d338437c90065", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "b75eb1ed61d9fb337f9be329ddb8a916120784a314c57d06dddff14977939c45", + "start_line": 583, + "name": "send_continue", + "arity": 2 + }, + "start_link/3:453": { + "line": 453, + "guard": null, + "pattern": "module, task_supervisor, opts", + "kind": "def", + "end_line": 471, + "ast_sha": "18acd1bac5800499afa9b47e174a9d389e372799de751ed14577e77f8d61673c", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "6a298ad7b4a27f70d4dbbda1a102d5915d566d3d04e7cb5f3ff24df0da6a1432", + "start_line": 453, + "name": "start_link", + "arity": 3 + }, + "topic_presences_count/2:727": { + "line": 727, + "guard": null, + "pattern": "topics, topic", + "kind": "defp", + "end_line": 728, + "ast_sha": "da803893fbd700cc5e5d01634e81632fb2694c04c020d1531e93f56b33da564a", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "249170c84176285f6aadfdc6244009371202dec8b405c1d37ea3d76512f4c4cc", + "start_line": 727, + "name": "topic_presences_count", + "arity": 2 + } + }, + "Phoenix.Endpoint.RenderErrors": { + "__before_compile__/1:33": { + "line": 33, + "guard": null, + "pattern": "_", + "kind": "defmacro", + "end_line": 47, + "ast_sha": "82c6ae09d909d92c52a539a5a87de0f228c5423e7b0536bd3c821192ef4be6f4", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "108cf8ea564a291a46153998ebf300a5d7cee7784b3f78ae2136eb3f60c9a053", + "start_line": 33, + "name": "__before_compile__", + "arity": 1 + }, + "__catch__/5:54": { + "line": 54, + "guard": null, + "pattern": "%Plug.Conn{} = conn, kind, reason, stack, opts", + "kind": "def", + "end_line": 66, + "ast_sha": "d556beab6e43a7008010f41726c397ac13d411ee3efb4e31bf0b22a77dc28974", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "c72ad8b1048a21173da293ad43876cfba6515bede1410cce53f20672f7a3a938", + "start_line": 54, + "name": "__catch__", + "arity": 5 + }, + "__debugger_banner__/5:101": { + "line": 101, + "guard": null, + "pattern": "_conn, _status, _kind, %Phoenix.Router.NoRouteError{router: router}, _stack", + "kind": "def", + "end_line": 104, + "ast_sha": "712042a3d48fbe60ba34fd954770091d9b528342a95c4f1c10e4eacec2dd2193", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "8aaad5d82a4cb177e7335b0d7861a714294caba8576efe631adabddb204278ca", + "start_line": 101, + "name": "__debugger_banner__", + "arity": 5 + }, + "__debugger_banner__/5:108": { + "line": 108, + "guard": null, + "pattern": "_conn, _status, _kind, _reason, _stack", + "kind": "def", + "end_line": 108, + "ast_sha": "5c242f47cb826d0c976e1b24d1659469125944a91c9950ccc2674b1f93aa6654", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "eb78e7c81032ca52c12216ad3a888bdb7128b5217db70c3617968aa4b2da4a4d", + "start_line": 108, + "name": "__debugger_banner__", + "arity": 5 + }, + "__using__/1:25": { + "line": 25, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 28, + "ast_sha": "03d04ec64c48e45a3bf2942630bc6d452ce547d3d03b6507626fb72ac789f4f9", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "aae761bfe89bfbad3cee2da81048e90e3211c1600b1d50c1f320f01be879366c", + "start_line": 25, + "name": "__using__", + "arity": 1 + }, + "error_conn/3:92": { + "line": 92, + "guard": null, + "pattern": "_conn, :error, %Phoenix.Router.NoRouteError{conn: conn}", + "kind": "defp", + "end_line": 92, + "ast_sha": "faddf17b94fd077836bd425ea74ff7fa3f357b2f653981b7ccd1743addf09138", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "bc50bec290e264e2d1002872bc84f37f13a189b3b00b21822b643176e99c3c9e", + "start_line": 92, + "name": "error_conn", + "arity": 3 + }, + "error_conn/3:93": { + "line": 93, + "guard": null, + "pattern": "conn, _kind, _reason", + "kind": "defp", + "end_line": 93, + "ast_sha": "4749c1d4431d62aef0e3b862c06f851bc55595a27ff409ca815711956bfb5afd", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "b283ac64c7e3802d30f54b7f7ec72653479a17bac68121b9c2e65a4cfb062b8f", + "start_line": 93, + "name": "error_conn", + "arity": 3 + }, + "fetch_view_format/2:137": { + "line": 137, + "guard": null, + "pattern": "conn, opts", + "kind": "defp", + "end_line": 152, + "ast_sha": "62a217dc8fd729264ea1a91a4abe7b1256e79635d48c0271fd2603eb4c1a5aa6", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "c2311426aca2b904cbd27666cfae148f442b53caadc48f7cfdd8fd27d4f788d2", + "start_line": 137, + "name": "fetch_view_format", + "arity": 2 + }, + "instrument_render_and_send/5:69": { + "line": 69, + "guard": null, + "pattern": "conn, kind, reason, stack, opts", + "kind": "defp", + "end_line": 88, + "ast_sha": "a0e6e9bca6c453be181f14739f537cabdf247341f78b294152f423432744fe71", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "0ac4d5eb7e5671d7a5a96d8e276a52f0541c4a6bc9783466b6a7f0a8abe606bc", + "start_line": 69, + "name": "instrument_render_and_send", + "arity": 5 + }, + "maybe_fetch_query_params/1:127": { + "line": 127, + "guard": null, + "pattern": "%Plug.Conn{} = conn", + "kind": "defp", + "end_line": 133, + "ast_sha": "9a13af80b2f0bbb32febe2418d6215c809885505854f9461cc8e7d5bd739a268", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "33796c8e5551b5388cc66ad5627584514ef0365870b878c6831a32b5fe7ded65", + "start_line": 127, + "name": "maybe_fetch_query_params", + "arity": 1 + }, + "maybe_raise/3:95": { + "line": 95, + "guard": null, + "pattern": ":error, %Phoenix.Router.NoRouteError{}, _stack", + "kind": "defp", + "end_line": 95, + "ast_sha": "bca3ba06070c1f77b204d3097c862e2e4e2e8a5fb8772cfbc8650204b3b2dbe8", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "38abb91bc08609f0bada9357c6588646851f9f39613a87276545d0411b0ee7cc", + "start_line": 95, + "name": "maybe_raise", + "arity": 3 + }, + "maybe_raise/3:96": { + "line": 96, + "guard": null, + "pattern": "kind, reason, stack", + "kind": "defp", + "end_line": 96, + "ast_sha": "a0365a7f795aedfa980c39aa62ce9a51ce4f80201a20b268402642d15c8b39ca", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "8f978c6675c22d695969dd2040baeae15fa1310e547616aa369e31fd38415143", + "start_line": 96, + "name": "maybe_raise", + "arity": 3 + }, + "put_formats/2:156": { + "line": 156, + "guard": null, + "pattern": "conn, formats", + "kind": "defp", + "end_line": 188, + "ast_sha": "9cff9b410ccbabd0cff7c4a81fe20f573aaa4207e6c503ca1052415952dce11d", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "58f66d603cdbd95faafa972d2f3d7740736757e06dd71f0ab3cf7d797e0c2981", + "start_line": 156, + "name": "put_formats", + "arity": 2 + }, + "render/6:110": { + "line": 110, + "guard": null, + "pattern": "conn, status, kind, reason, stack, opts", + "kind": "defp", + "end_line": 124, + "ast_sha": "21a29a6b65abcd605cdc601d83959479fd2fc4f72374e70ea3a5f48913c27dad", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "9618fe666c4ec1d71bd1eb723eb1281e99398e218cb5feb0db95e125904f7e2b", + "start_line": 110, + "name": "render", + "arity": 6 + }, + "status/2:192": { + "line": 192, + "guard": null, + "pattern": ":error, error", + "kind": "defp", + "end_line": 192, + "ast_sha": "8b904952f554edbc193955ef2baf64a707854315787d221d86d9e75a0319374e", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "dd9db662eb5f46e31a4aff99d1fec71f8ab3a3cbbe70147da7f4dc0848d3c970", + "start_line": 192, + "name": "status", + "arity": 2 + }, + "status/2:193": { + "line": 193, + "guard": null, + "pattern": ":throw, _throw", + "kind": "defp", + "end_line": 193, + "ast_sha": "52b4c588afd73d6c190f97da20b381d0a890441731c3d4c41e5c523e93968d64", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "a7c99cd9a8218667a4608e938a8ff5bed3c651db5dd5224cc5895a80865ebfef", + "start_line": 193, + "name": "status", + "arity": 2 + }, + "status/2:194": { + "line": 194, + "guard": null, + "pattern": ":exit, _exit", + "kind": "defp", + "end_line": 194, + "ast_sha": "1274b943a7cbc8c46bccd0148de953a937513d8fc939bdf215dc52e05db8ae64", + "source_file": "lib/phoenix/endpoint/render_errors.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", + "source_sha": "4520cd93fdb485c3653c5a2afedcf1fcbb9a68f1c4bb0fcc684db0ae3bbf1a94", + "start_line": 194, + "name": "status", + "arity": 2 + } + }, + "Mix.Phoenix.Schema": { + "live_form_value/1:221": { + "line": 221, + "guard": null, + "pattern": "%Time{} = time", + "kind": "def", + "end_line": 221, + "ast_sha": "ef538e7121da66ab7540617e7f6ae917b5dd360842489dc13153ef08d7696384", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "b44c81b3eed4f21833692097c1b77c5aa8bf9563dce3ac0dca2ff46615cc1a1b", + "start_line": 221, + "name": "live_form_value", + "arity": 1 + }, + "maybe_redact_field/1:278": { + "line": 278, + "guard": null, + "pattern": "true", + "kind": "def", + "end_line": 278, + "ast_sha": "54870f06dd63c37caf53ea2492c4cbfed86cf6698d07c06c463cfe19fc2cd3e5", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ddcf1f8f791f983022ff6587d19e200e7d5bcecb85ffdfe19808dcbae717ebaf", + "start_line": 278, + "name": "maybe_redact_field", + "arity": 1 + }, + "build_enum_values/2:404": { + "line": 404, + "guard": null, + "pattern": "values, action", + "kind": "defp", + "end_line": 408, + "ast_sha": "9e0d4fce96831153e7acb724212d79d7f2d9428537ce6526e91a2ee0cdb0580e", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "d24d70f98ae5fb6d183698f9ba2c41d626d18d76edd7f4f6cb67a90769ac42c0", + "start_line": 404, + "name": "build_enum_values", + "arity": 2 + }, + "build_array_values/2:398": { + "line": 398, + "guard": null, + "pattern": ":integer, :update", + "kind": "defp", + "end_line": 398, + "ast_sha": "e6363b4a5d163caa2580100778b7812b04bb3ba223d31ec564df70eb9d52664e", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "47b98410d0580dd630840f6f9c8bb85c0dbe6e9295f7426a08b16fdb407f7c9f", + "start_line": 398, + "name": "build_array_values", + "arity": 2 + }, + "build_utc_datetime_usec/0:412": { + "line": 412, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 413, + "ast_sha": "7d08059f69173f08ddf46000f54aef651d3ff2046641d219be58ae6b7cf3fbd1", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "8c0882fda11ecefe43fcb2a59d6d4316f8ed8828e4cc852fe9cb1c4f2fe9ef02", + "start_line": 412, + "name": "build_utc_datetime_usec", + "arity": 0 + }, + "partition_attrs_and_assocs/3:453": { + "line": 453, + "guard": null, + "pattern": "schema_module, attrs, scope", + "kind": "defp", + "end_line": 481, + "ast_sha": "9647394e096df223aafb9b74695d7f5758d41e21ff8c47bcb51c2889de74adda", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ee9f68904f27acf1e1587a77bb0b7c5b5f9090bef96992333259feb60c50e05f", + "start_line": 453, + "name": "partition_attrs_and_assocs", + "arity": 3 + }, + "maybe_redact_field/1:279": { + "line": 279, + "guard": null, + "pattern": "false", + "kind": "def", + "end_line": 279, + "ast_sha": "000d291874dae900a9be63ced128afd096b73fa58f9741f5acbfb347943a59dc", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "4c3dcbb08f7e227a9591f9f6726a906f2df4cde25e1c3197503a1b1a583accdd", + "start_line": 279, + "name": "maybe_redact_field", + "arity": 1 + }, + "fixture_unique_functions/3:580": { + "line": 580, + "guard": null, + "pattern": "singular, uniques, attrs", + "kind": "defp", + "end_line": 615, + "ast_sha": "d77752e611c7fa7f28cdff9e937076e3ecf431db7e188562a5c445b5520af8e7", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "5793ad5d76d15b8e52a779f92b9b01ffb940dece8d569d382c020734252f51a4", + "start_line": 580, + "name": "fixture_unique_functions", + "arity": 3 + }, + "list_to_attr/1:296": { + "line": 296, + "guard": null, + "pattern": "[key, comp, value]", + "kind": "defp", + "end_line": 297, + "ast_sha": "bf2eb4b83019ed5e920c853d7cee16e41fb1fcdb98fa35676b437efe4cb9d93c", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "5bc38da584c77c2c80d25f39ade781090a126d36d75b95d3a074ecff855d3999", + "start_line": 296, + "name": "list_to_attr", + "arity": 1 + }, + "validate_scope_and_reference_conflict!/2:484": { + "line": 484, + "guard": null, + "pattern": "%Mix.Phoenix.Scope{schema_key: reference_key}, reference_key", + "kind": "defp", + "end_line": 489, + "ast_sha": "15cc8c5b531676a0f2552ba85100294c6574aa21c94b3ed3f57046506f811c59", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "b02b3c82405ad462760c0f7aa1a14023ef126189f1bcdf11a023c42a041dc6b8", + "start_line": 484, + "name": "validate_scope_and_reference_conflict!", + "arity": 2 + }, + "type_to_default/3:367": { + "line": 367, + "guard": null, + "pattern": "key, t, :update", + "kind": "defp", + "end_line": 385, + "ast_sha": "7944c7c01318ab9a5c6f5ec1d6005d8a163687edb32d3aa6b10571204efc83e7", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "593b5159a2a3d1c2989a2fe084891639c25eb213ff8076dc84799900c6d653f4", + "start_line": 367, + "name": "type_to_default", + "arity": 3 + }, + "params/2:209": { + "line": 209, + "guard": "=:=(action, :create) or =:=(action, :update)", + "pattern": "attrs, action", + "kind": "def", + "end_line": 210, + "ast_sha": "90e71646e8f137f9af7b82baad2b545fb674b5d3487d73246ceb8f617da04782", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "78d4de099efca017b6b2bce315890a3fb2ab64e8f3b9d51730e333e1175b561f", + "start_line": 209, + "name": "params", + "arity": 2 + }, + "type_for_migration/1:256": { + "line": 256, + "guard": null, + "pattern": "{:enum, _}", + "kind": "def", + "end_line": 256, + "ast_sha": "462756be699666ecf17e71bcd40bdbd2a4f5401be722f4d79846ef00183ec9bd", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "9f79fabbdf26a0cb5b53c84a0f94e0815002130bb603f91b67c25c020174426d", + "start_line": 256, + "name": "type_for_migration", + "arity": 1 + }, + "list_to_attr/1:294": { + "line": 294, + "guard": null, + "pattern": "[key, value]", + "kind": "defp", + "end_line": 294, + "ast_sha": "a4b07491dccbdf8972dadf4d2934e9fb1cd435352e96ccf510dce6aa491f22fe", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "62c51055e549562a0bc88ccd0e3e89ddbbbd5fceb964d30148f3a61d9f674fac", + "start_line": 294, + "name": "list_to_attr", + "arity": 1 + }, + "migration_module/0:573": { + "line": 573, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 576, + "ast_sha": "381265538d03f9f8feba307572e7d8dacf1c43a69acb07a8ba8844d2c0418120", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "8d414873f81da75065ee0c715daab12655cc6a39010b330a3d682b0c52b98831", + "start_line": 573, + "name": "migration_module", + "arity": 0 + }, + "type_and_opts_for_schema/1:273": { + "line": 273, + "guard": null, + "pattern": "{:enum, opts}", + "kind": "def", + "end_line": 274, + "ast_sha": "50df40637caae958cc247f1b0c26bd2aaf679905c8730934776bbe7c6186c543", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "29385e3ba7b39c8612042d062cb125183acd97d242f65c6dc8905220bd374ddc", + "start_line": 273, + "name": "type_and_opts_for_schema", + "arity": 1 + }, + "build_array_values/2:401": { + "line": 401, + "guard": null, + "pattern": "_, _", + "kind": "defp", + "end_line": 401, + "ast_sha": "b535731167206a53b9c17a959c5243c11babb12052fad89f66b6d524d7c657a7", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "853769d0266179c6b0ea316c8c725610da47abab56170e4389590fa11525fd86", + "start_line": 401, + "name": "build_array_values", + "arity": 2 + }, + "route_helper/2:562": { + "line": 562, + "guard": null, + "pattern": "web_path, singular", + "kind": "defp", + "end_line": 565, + "ast_sha": "6cc400a82155a75348293d0865ecfa9264b343bbcdd4dc5123ccb786ed05599a", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "538371183c75873f695d06e9ac3ae305cd9cd7ceb6c489e390637ed661b0c54d", + "start_line": 562, + "name": "route_helper", + "arity": 2 + }, + "valid_types/0:69": { + "line": 69, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 69, + "ast_sha": "e0f7990f452bbee24b7928c176eb46c5fb3d22f7a1575e29ca2621466505412f", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "1d983e6cea12a035775e82ac70ea5474f3e5a8eb7deca96e24ffbb3e3f300144", + "start_line": 69, + "name": "valid_types", + "arity": 0 + }, + "type_and_opts_for_schema/1:276": { + "line": 276, + "guard": null, + "pattern": "other", + "kind": "def", + "end_line": 276, + "ast_sha": "f50e8cf37b0e2cc41465dfa8c9656e03f1394dece7abd25731e36093fecef5c0", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "c2ec5e7ac303f713291ac23f9d48cf1cf7fff1fc03cb2314ac90d19b4af58c96", + "start_line": 276, + "name": "type_and_opts_for_schema", + "arity": 1 + }, + "validate_attr!/1:443": { + "line": 443, + "guard": "=:=(type, :integer) or =:=(type, :float) or =:=(type, :decimal) or =:=(type, :boolean) or\n =:=(type, :map) or =:=(type, :string) or =:=(type, :array) or =:=(type, :references) or\n =:=(type, :text) or =:=(type, :date) or =:=(type, :time) or =:=(type, :time_usec) or\n =:=(type, :naive_datetime) or =:=(type, :naive_datetime_usec) or =:=(type, :utc_datetime) or\n =:=(type, :utc_datetime_usec) or =:=(type, :uuid) or =:=(type, :binary) or =:=(type, :enum)", + "pattern": "{_name, type} = attr", + "kind": "defp", + "end_line": 443, + "ast_sha": "610ddd864a575d5b0d3f0881888ce71b0e7bd0728dc4d541f43db88831ead2fa", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "e6bed7fe2837eef09242a4363babfb514255bb96a83a808869b5683ed46fab9a", + "start_line": 443, + "name": "validate_attr!", + "arity": 1 + }, + "__struct__/1:6": { + "line": 6, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 6, + "ast_sha": "adff79d2c708b4c68abfa00c4ba78ecb1b8b4921e6b7a40620b0b9840b23e2af", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "d2cd594a48ad511cc35d57efe9641417e24ea647197f26f1c4ae61b6400bf0a6", + "start_line": 6, + "name": "__struct__", + "arity": 1 + }, + "indexes/3:535": { + "line": 535, + "guard": null, + "pattern": "table, assocs, uniques", + "kind": "defp", + "end_line": 543, + "ast_sha": "d4a632e43ac965d56952cc5c124e847bc0c6ee9979dbd60a9327544d20111c8b", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "27a8dc8bdbe2da5f7e4f7feb4632ecd6f34dcf061ac30fc6ae79e3c75c7f2c13", + "start_line": 535, + "name": "indexes", + "arity": 3 + }, + "type_for_migration/1:257": { + "line": 257, + "guard": null, + "pattern": "other", + "kind": "def", + "end_line": 257, + "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "5a2f9b57fce3fb2fdb6e175409fa9a8768c6f45837b303a8afcad6af7121c273", + "start_line": 257, + "name": "type_for_migration", + "arity": 1 + }, + "list_to_attr/1:293": { + "line": 293, + "guard": null, + "pattern": "[key]", + "kind": "defp", + "end_line": 293, + "ast_sha": "0ad3fbc70511dae36638ab5feebc9c09166e6fd10b67ccd611029717a1455373", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "bed72be1096c060784b46b63af252a6d33e5e11c589f34749d20b7f8f9ccec34", + "start_line": 293, + "name": "list_to_attr", + "arity": 1 + }, + "extract_attr_flags/1:174": { + "line": 174, + "guard": null, + "pattern": "cli_attrs", + "kind": "def", + "end_line": 182, + "ast_sha": "db50078f1ce357ffb224353bc0e26c39c778267725c1ef503b568c5949241ff2", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "cb1afe1891f03224319f969c647cd4fc930193ced744c64f8ebbb84c99d4abcc", + "start_line": 174, + "name": "extract_attr_flags", + "arity": 1 + }, + "inspect_value/2:291": { + "line": 291, + "guard": null, + "pattern": "_type, value", + "kind": "defp", + "end_line": 291, + "ast_sha": "12e309937a294602e94fb940dc70e135f2769643dc80033b3758e07323ce8554", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "0d17ff7e2a6f905337e2631503e4c2802aca549b075e06a27ba6c78e8d7a7d8e", + "start_line": 291, + "name": "inspect_value", + "arity": 2 + }, + "build_array_values/2:389": { + "line": 389, + "guard": null, + "pattern": ":string, :create", + "kind": "defp", + "end_line": 390, + "ast_sha": "d1a6759c19f5628d18c2f081f3904fc594883e0bd3091d89292cac15885c2fe7", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "8869ece9023f4a2dcad454fb444e9ca2330ed529a7f21b40d021f3c483d2ec42", + "start_line": 389, + "name": "build_array_values", + "arity": 2 + }, + "types/1:509": { + "line": 509, + "guard": null, + "pattern": "attrs", + "kind": "defp", + "end_line": 513, + "ast_sha": "f22d61bc9536383c3fe65166cd72bed3f2166e0eb1e7b58ce0e658a0e8a8e529", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "a8a39ebb7316c0ad47bcc1fe3f985aea1065c0a83a88198ee73b5bca484c74c4", + "start_line": 509, + "name": "types", + "arity": 1 + }, + "invalid_form_value/1:240": { + "line": 240, + "guard": "is_list(value)", + "pattern": "value", + "kind": "def", + "end_line": 240, + "ast_sha": "5761b9d3c40e935d9785f8b8d65755ba4f3b92c72205c243b52ba28e3d50e4e1", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "2aeee5f8c8a9e379eb0a0f30033f0ee5b9b2a87af1b4e5c3efd7194c35d291f9", + "start_line": 240, + "name": "invalid_form_value", + "arity": 1 + }, + "build_utc_naive_datetime/0:421": { + "line": 421, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 422, + "ast_sha": "fae2f99c9bb071e2bb97fb10ee6b3876c45e37bb887257d587d89a1003501428", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "078959c85e54f4daec7fb43aee992eedbbabd7cf57737395d35b016942b36d3f", + "start_line": 421, + "name": "build_utc_naive_datetime", + "arity": 0 + }, + "invalid_form_value/1:247": { + "line": 247, + "guard": null, + "pattern": "_value", + "kind": "def", + "end_line": 247, + "ast_sha": "634349d9494dffcf415d3e0328fa0a36e6434ed2d40946019e4b62991518f942", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "6fc8d628abd4c6795f8953cc733f179896eaa4e636ab25753725374afb01544a", + "start_line": 247, + "name": "invalid_form_value", + "arity": 1 + }, + "split_flags/5:188": { + "line": 188, + "guard": null, + "pattern": "[\"redact\" | rest], name, attrs, uniques, redacts", + "kind": "defp", + "end_line": 189, + "ast_sha": "e0bcb0ffd93ed34d3c1723d62e7d51191624a9610df10dcee7800af12aa80362", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "11dd31c7ba9a7fcbe09d06a6c571fe528db8b4436cac4ce48a753fa8a5cae221", + "start_line": 188, + "name": "split_flags", + "arity": 5 + }, + "schema_defaults/1:495": { + "line": 495, + "guard": null, + "pattern": "attrs", + "kind": "defp", + "end_line": 498, + "ast_sha": "396fd860a8dc3878ce137032bc164994f9c59892283a8d933af24da6883cd4fe", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f86a36e8f72a1c852fe222e3ef8b056b466d2c9d5e2363a4e10be9dcd023e31a", + "start_line": 495, + "name": "schema_defaults", + "arity": 1 + }, + "invalid_form_value/1:242": { + "line": 242, + "guard": null, + "pattern": "%{day: _day, month: _month, year: _year} = _date", + "kind": "def", + "end_line": 242, + "ast_sha": "ebb85777a0847ff608e32b2ffbc592901dfa1bae3aa6d26ab90f883aa77d51fe", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "e14c396654f1e6f65a0ec44e95323a2526990c164d498e899fda04192e68f800", + "start_line": 242, + "name": "invalid_form_value", + "arity": 1 + }, + "inspect_value/2:290": { + "line": 290, + "guard": null, + "pattern": ":decimal, value", + "kind": "defp", + "end_line": 290, + "ast_sha": "36de7841eef5264c2a489e05bd2d68d1509c7724fe947c343168c518270185a7", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "c0ba4fcd57abf3b2e3bebccb7a15bdaa82a4327ae10d2d091938d4f94d389e74", + "start_line": 290, + "name": "inspect_value", + "arity": 2 + }, + "format_fields_for_schema/1:259": { + "line": 259, + "guard": null, + "pattern": "schema", + "kind": "def", + "end_line": 261, + "ast_sha": "ff86a67f617df8300c555e1584f1478289a16bff8913857b3560a48e6d37ebb8", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "9ca2f63de0ec6593e89441f0d63300f5b29cb2f9f9e610adbe0ff63a602e120c", + "start_line": 259, + "name": "format_fields_for_schema", + "arity": 1 + }, + "split_flags/5:185": { + "line": 185, + "guard": null, + "pattern": "[\"unique\" | rest], name, attrs, uniques, redacts", + "kind": "defp", + "end_line": 186, + "ast_sha": "64e11ec1aac721ef4d861919618286614b504486b684ccefbca77c8faee5faed", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "2e8480e64c50f46f9b40431d4b8c59e8d4f2ff82c97a716734d68b1992bb49b6", + "start_line": 185, + "name": "split_flags", + "arity": 5 + }, + "default_param/2:167": { + "line": 167, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema, action", + "kind": "def", + "end_line": 171, + "ast_sha": "bd6d821ba884d812b9407ec73aa67b928eefb8ea3aed97b7303b72f6f60392b0", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "9bdb068f4b8dcad88bc8dd88f0d0670fc177d83e3b57f35f759e1744510e2ac7", + "start_line": 167, + "name": "default_param", + "arity": 2 + }, + "live_form_value/1:219": { + "line": 219, + "guard": null, + "pattern": "%Date{} = date", + "kind": "def", + "end_line": 219, + "ast_sha": "01cc67489f241f7a3f7e49f4b7e4d7d30255b3af395a5c4464d9050ede0a3cbd", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ed004aeb270d9641a896969965c50e4083192376f629ab5296c381c3059ed8dc", + "start_line": 219, + "name": "live_form_value", + "arity": 1 + }, + "validate_attr!/1:446": { + "line": 446, + "guard": null, + "pattern": "{_, type}", + "kind": "defp", + "end_line": 449, + "ast_sha": "f9cca53eea1e58d2040cfbd1ce5672e7c4fb76b5ea18c8b133414f1bf2e00a9f", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "a8cfc19e79201ac16f1b2bcfb03e31c4b81fbeea2bcdb3401ffd8b71b0dfd197", + "start_line": 446, + "name": "validate_attr!", + "arity": 1 + }, + "schema_type/1:527": { + "line": 527, + "guard": null, + "pattern": "val", + "kind": "defp", + "end_line": 531, + "ast_sha": "8602be6b10bafc5846401847978b0f39e2a9f45fe0af38608f7eb0c62f832e42", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "7965e824f612530eaf76dd638246315a7878275e9460011e5e829d1430691be0", + "start_line": 527, + "name": "schema_type", + "arity": 1 + }, + "type_to_default/3:302": { + "line": 302, + "guard": null, + "pattern": "key, t, :create", + "kind": "defp", + "end_line": 363, + "ast_sha": "38f7a1f08ddabe56e06e62edb0270be911c71f6d3385082c5764d2e55e743a63", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f06365b3b0cfaff3815ac5e2a08eb9922c745b5b4f19185c7b9d25a6e4af7c56", + "start_line": 302, + "name": "type_to_default", + "arity": 3 + }, + "build_array_values/2:392": { + "line": 392, + "guard": null, + "pattern": ":integer, :create", + "kind": "defp", + "end_line": 392, + "ast_sha": "3c25924e53530ac1a7f76a764e7e74baf469b5309197210a00f6574bec2d7323", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "0666118eb18734edd0e3b7d4a22034caec8489ab94abaa9c19545efa232b0bee", + "start_line": 392, + "name": "build_array_values", + "arity": 2 + }, + "build_utc_datetime/0:415": { + "line": 415, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 416, + "ast_sha": "1e420ba105637d02affe391a4e68d5e724a489d4ac5505eb4ee543c40bad23a8", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "3c0557b24102edcae647327cb80ae134a31fdcb21060d1eea8cca3fd9564a05f", + "start_line": 415, + "name": "build_utc_datetime", + "arity": 0 + }, + "value/3:284": { + "line": 284, + "guard": null, + "pattern": "schema, field, value", + "kind": "def", + "end_line": 287, + "ast_sha": "90de58bccc18df4b2c60b0be20a7dc221f9efab9765715dec25439d9909b5d64", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "2c215426fffc891c379fbe20cecab225145af0fd45bdcf4f7d19b91903fc89f8", + "start_line": 284, + "name": "value", + "arity": 3 + }, + "params/1:209": { + "line": 209, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 209, + "ast_sha": "1ed77c9d852b04303003a09cf35fe3ce3a0dfbdb482fe6b69c1f1420e19ad097", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "350397c7684734c772a7d78f81ce4969ca07e2281294eb325d988cee155dfe4c", + "start_line": 209, + "name": "params", + "arity": 1 + }, + "new/4:75": { + "line": 75, + "guard": null, + "pattern": "schema_name, schema_plural, cli_attrs, opts", + "kind": "def", + "end_line": 160, + "ast_sha": "941841b24f713aa730487b659f607b1fb2f157e0554874c24ba4153de978526a", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "c16936e6b625a24acad3cefbbf9c83d1a78e13428f337115103e402b820d3732", + "start_line": 75, + "name": "new", + "arity": 4 + }, + "fixture_params/2:619": { + "line": 619, + "guard": null, + "pattern": "attrs, fixture_unique_functions", + "kind": "defp", + "end_line": 628, + "ast_sha": "3a11264ce911aaa91b5ba6263c890e9bb3d3a68bb6c3b28d4a0bce4cc224f02a", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "a603037b49c2de03f8a536ca462f8f66b1061968c299c404bc7236e6241fdbaf", + "start_line": 619, + "name": "fixture_params", + "arity": 2 + }, + "required_fields/1:269": { + "line": 269, + "guard": null, + "pattern": "schema", + "kind": "def", + "end_line": 270, + "ast_sha": "f3eddcf0aae25947fddbe2777d984feac53466028ae01167b5c2a9ba9e745b1b", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "cfa687658fad46ce8bf44d920183b5b6565496a1f15a62ef8f87c464c171401d", + "start_line": 269, + "name": "required_fields", + "arity": 1 + }, + "live_form_value/1:227": { + "line": 227, + "guard": null, + "pattern": "%DateTime{} = naive", + "kind": "def", + "end_line": 228, + "ast_sha": "2028d03554099af8379b1f305b209290e951b96fcbf2187ed8edbe2f57b9df58", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "1f888cec8ce978df0292187cc0cd8143451a33f61bcf7eeacac499ba925cfa20", + "start_line": 227, + "name": "live_form_value", + "arity": 1 + }, + "__struct__/0:6": { + "line": 6, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 6, + "ast_sha": "e306b77ceb58c149d9cb03cbe70af8916e9adc98b8aaa4e0c98d441e58ad20a1", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "d2cd594a48ad511cc35d57efe9641417e24ea647197f26f1c4ae61b6400bf0a6", + "start_line": 6, + "name": "__struct__", + "arity": 0 + }, + "schema_type/1:525": { + "line": 525, + "guard": null, + "pattern": ":uuid", + "kind": "defp", + "end_line": 525, + "ast_sha": "f0d8ff6cd9cbe32eebec9b5ffd82936524f91b3c2c5293de14fb0032cb89ec79", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "52c6680c40b9dbe8b1c964fa0a564cbc46861028cff1b75ef4b2b2729e9bbf46", + "start_line": 525, + "name": "schema_type", + "arity": 1 + }, + "live_form_value/1:231": { + "line": 231, + "guard": null, + "pattern": "value", + "kind": "def", + "end_line": 231, + "ast_sha": "49ddea2d3a43e2fd798386394567ead0e1fe27bedded580f2537b308c7901e59", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "80a900aa415424c1aa12abdc6287fba4bc6124231685c133facf5286456f3cf2", + "start_line": 231, + "name": "live_form_value", + "arity": 1 + }, + "attrs/1:197": { + "line": 197, + "guard": null, + "pattern": "attrs", + "kind": "def", + "end_line": 202, + "ast_sha": "ce0ac0b134e77b3b47a1cff618afa76860e72f44fc46408b3c4575d3a35f1d4e", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ea744d6fa585289e0d85282f71bf5ee92ab19f0067f1847dafb7ec6e66e485ba", + "start_line": 197, + "name": "attrs", + "arity": 1 + }, + "string_attr/1:502": { + "line": 502, + "guard": null, + "pattern": "types", + "kind": "defp", + "end_line": 505, + "ast_sha": "50aba7bbd709d97d7ad2423751ab2b98193e84322ff05f726363ef1891775569", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "3051083a52a2c33601c3664da27f9b659caeb44c60d60884e3f16879fbc8d009", + "start_line": 502, + "name": "string_attr", + "arity": 1 + }, + "schema_type/1:524": { + "line": 524, + "guard": null, + "pattern": ":text", + "kind": "defp", + "end_line": 524, + "ast_sha": "fb499b23292b1f2577fa0fff47d4b1666bbd3e46fbc61601f57cb3859c813d79", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "46225aef5557ef1b905ae9f7485e9c70e6b44d134e30082adaea88d45693d766", + "start_line": 524, + "name": "schema_type", + "arity": 1 + }, + "migration_defaults/1:547": { + "line": 547, + "guard": null, + "pattern": "attrs", + "kind": "defp", + "end_line": 550, + "ast_sha": "a58bf9538f7c444c24b22180021812d016656d8ab4a16ade026cdbddfc5e5079", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f88451621150ebae69586d57f70e8328bcd8816717689c796fe5db1b9d1db708", + "start_line": 547, + "name": "migration_defaults", + "arity": 1 + }, + "valid?/1:71": { + "line": 71, + "guard": null, + "pattern": "schema", + "kind": "def", + "end_line": 72, + "ast_sha": "9e1affdfbd037feb6b3a6802b0ada912c3572184071e644bcb254daa2b0f8b15", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "4d6e7aab6858bd3a253a960903f4c76acdef86a48ea79165f1dee77e0dbe3931", + "start_line": 71, + "name": "valid?", + "arity": 1 + }, + "failed_render_change_message/1:252": { + "line": 252, + "guard": null, + "pattern": "_schema", + "kind": "def", + "end_line": 252, + "ast_sha": "b5bbb1a4ba62a70f2019d233906472be53875f77ffc506d290a41499aa01e2c6", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "af590b0bad262f1e70b6ebe1a7ea0a617a5e7ad5306a76c2d1bfe5b56f7be1cf", + "start_line": 252, + "name": "failed_render_change_message", + "arity": 1 + }, + "validate_attr!/1:433": { + "line": 433, + "guard": null, + "pattern": "{name, :array}", + "kind": "defp", + "end_line": 435, + "ast_sha": "27ac89f0e13e777097b5bed75000641eceef3ee0ba39ec01a80032b57b0c3ef2", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "e56503ec04214aa965df69790720b25cda38aeb5da4ab86f12a0bf68e2152cb8", + "start_line": 433, + "name": "validate_attr!", + "arity": 1 + }, + "validate_attr!/1:444": { + "line": 444, + "guard": "=:=(type, :integer) or =:=(type, :float) or =:=(type, :decimal) or =:=(type, :boolean) or\n =:=(type, :map) or =:=(type, :string) or =:=(type, :array) or =:=(type, :references) or\n =:=(type, :text) or =:=(type, :date) or =:=(type, :time) or =:=(type, :time_usec) or\n =:=(type, :naive_datetime) or =:=(type, :naive_datetime_usec) or =:=(type, :utc_datetime) or\n =:=(type, :utc_datetime_usec) or =:=(type, :uuid) or =:=(type, :binary) or =:=(type, :enum)", + "pattern": "{_name, {type, _}} = attr", + "kind": "defp", + "end_line": 444, + "ast_sha": "95459accde92b128e6ab9d7fa2f8a0274227213b2641dab80b8c771ef529b19b", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "b474dad803a91f0434d4fadc65856447d6af1cdc9f25f80a25675eed29318d12", + "start_line": 444, + "name": "validate_attr!", + "arity": 1 + }, + "sample_id/1:554": { + "line": 554, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 556, + "ast_sha": "5cb59bfec6c9163766a4abfdaea00a1dc7ba55d6689bc8d0cffbb98aa9e372db", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ed65b909c585cf6cf926a1fcf99f2bff3ac51d2a5d677a775baa2483f8a757f7", + "start_line": 554, + "name": "sample_id", + "arity": 1 + }, + "build_utc_naive_datetime_usec/0:418": { + "line": 418, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 419, + "ast_sha": "da945f787ebd2ccc40e90ec37b6db2c8278a8a6e847310a60e4dae617d3f1a24", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "bd8956dbb377a027fc687b53b8e97bad4e5a3352bef68086d3eeaeb2095dfd3e", + "start_line": 418, + "name": "build_utc_naive_datetime_usec", + "arity": 0 + }, + "validate_scope_and_reference_conflict!/2:493": { + "line": 493, + "guard": null, + "pattern": "_scope, _source", + "kind": "defp", + "end_line": 493, + "ast_sha": "70075dd5964b0bdeeecc8ab6d8232362a1d4c5236b141b1524e7d23a6ec5ddfe", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f1d6ec06de22d8e9b48993900ba8a0bec43aa58dbb69ae3ed670f6a1484dd5a3", + "start_line": 493, + "name": "validate_scope_and_reference_conflict!", + "arity": 2 + }, + "translate_enum_vals/1:517": { + "line": 517, + "guard": null, + "pattern": "vals", + "kind": "def", + "end_line": 521, + "ast_sha": "9588a831ccf6eb119828615a7f92ced1330d7160766f3703d16da9c9efcdc918", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "2e149a358cbe73d4166b53e4502e7a3614b688f1a67d67ba37833099cf393867", + "start_line": 517, + "name": "translate_enum_vals", + "arity": 1 + }, + "invalid_form_value/1:246": { + "line": 246, + "guard": null, + "pattern": "true", + "kind": "def", + "end_line": 246, + "ast_sha": "955067d85247ecc95bdfe88d397307d8c9d02f06e4e8daa27c7a843f06f18bd1", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "07018e65ec43e97fa20635b2f0c3f11c9ca8f2cfb0ea1e9924533983d0eb54a4", + "start_line": 246, + "name": "invalid_form_value", + "arity": 1 + }, + "build_array_values/2:395": { + "line": 395, + "guard": null, + "pattern": ":string, :update", + "kind": "defp", + "end_line": 395, + "ast_sha": "15f679594b16db733c4cce6413d1519a217e6c59eaf9ca73fe329a3872bdf28c", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f093876506f164d24bda31dbe207408f417465e7112d252371ba325863edc248", + "start_line": 395, + "name": "build_array_values", + "arity": 2 + }, + "split_flags/5:191": { + "line": 191, + "guard": null, + "pattern": "rest, name, attrs, uniques, redacts", + "kind": "defp", + "end_line": 192, + "ast_sha": "696955d69718bcae2a52bd94838a8222a3eaba88634fc90a0fbf5dd909d07e0d", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "ed49e58df778d30bb8ca998b1674bb079acb84a2ac2591e16e4450c729e22226", + "start_line": 191, + "name": "split_flags", + "arity": 5 + }, + "route_prefix/2:568": { + "line": 568, + "guard": null, + "pattern": "web_path, plural", + "kind": "defp", + "end_line": 570, + "ast_sha": "872b66d1894f1c64fbe006fa5ec82531069454cf7bd6db5d068c297e732c2887", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "f0312b7a532e60f46683237ab4261fc7b819b5dcbd3b4229a50f800e276b1e38", + "start_line": 568, + "name": "route_prefix", + "arity": 2 + }, + "validate_attr!/1:442": { + "line": 442, + "guard": null, + "pattern": "{_name, :enum}", + "kind": "defp", + "end_line": 442, + "ast_sha": "880f2952c69682c74b432b3ce74b4514959a85e43eae3d979e5d26672ff19d18", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "e6cb5a1a2a0f9df408d065a021a12d724e7c74843499c943e09e7ab8e660919d", + "start_line": 442, + "name": "validate_attr!", + "arity": 1 + }, + "invalid_form_value/1:245": { + "line": 245, + "guard": null, + "pattern": "%{hour: _hour, minute: _minute}", + "kind": "def", + "end_line": 245, + "ast_sha": "90fcd2ee04bba220e1c2abec7aa1b96636a51ecae365ed8385ffee04da20a53f", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "44cfe2dbfe276cdc86af61e4227553632424ad183c82bad1741bcfd69b667695", + "start_line": 245, + "name": "invalid_form_value", + "arity": 1 + }, + "validate_attr!/1:431": { + "line": 431, + "guard": null, + "pattern": "{name, :datetime}", + "kind": "defp", + "end_line": 431, + "ast_sha": "fca785ec6c439454787568c7dd7d7d05f1257f67f8c1d199603c7dc4184a5bdc", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "80bdc348908e63601bb5ee3abc57c05e3902c3ce9f3bc95d836844734e6dbdf0", + "start_line": 431, + "name": "validate_attr!", + "arity": 1 + }, + "live_form_value/1:223": { + "line": 223, + "guard": null, + "pattern": "%NaiveDateTime{} = naive", + "kind": "def", + "end_line": 224, + "ast_sha": "f9468d30ebc9cde309cc2fffa6d043ad6c9a53b740204ba0f25c163173aa31ed", + "source_file": "lib/mix/phoenix/schema.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", + "source_sha": "9067c2764cbcaf2cbcb76456747fb464e8f2f3d0bc75f70abcaa42bcc9db2895", + "start_line": 223, + "name": "live_form_value", + "arity": 1 + } + }, + "Phoenix.Debug": { + "channel_process?/1:86": { + "line": 86, + "guard": null, + "pattern": "pid", + "kind": "def", + "end_line": 94, + "ast_sha": "fb891be6011ad4769005bee70f75c9bba8d9426be0d467179dbaa8504efa93e2", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "14c7841dbd2231a5cd434bc4302b71b7c08936efa8a2b93948ce5de5dc11a3fb", + "start_line": 86, + "name": "channel_process?", + "arity": 1 + }, + "keyfind/2:44": { + "line": 44, + "guard": null, + "pattern": "list, key", + "kind": "defp", + "end_line": 47, + "ast_sha": "434ade879194dd4bba7ec4c978816f948191e5c6b3373725cc4f7c97e814da10", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "bbd0ed5ed0a4b889c7f679087182d497559425cf2a3281cf29bf44fd883efa96", + "start_line": 44, + "name": "keyfind", + "arity": 2 + }, + "list_channels/1:125": { + "line": 125, + "guard": null, + "pattern": "socket_pid", + "kind": "def", + "end_line": 135, + "ast_sha": "43d0a778f77d5d9f68ad56eece998bc8bf2216ad48c2120aa61493e69494b89e", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "918c15d4cb8ad5b562eceb19e4e78d7dbaa7bbc4155048f60b622ca3a299e166", + "start_line": 125, + "name": "list_channels", + "arity": 1 + }, + "list_sockets/0:37": { + "line": 37, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 40, + "ast_sha": "554271f1cdb8b0b25f901529782b908560fbd4e7967e3cdd1ccf02e905d70395", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "c93e563fb86afdff3e03e4e2d919cbd21ea8eb145db4b5c40addb01001d2db1e", + "start_line": 37, + "name": "list_sockets", + "arity": 0 + }, + "socket/1:159": { + "line": 159, + "guard": null, + "pattern": "channel_pid", + "kind": "def", + "end_line": 166, + "ast_sha": "182d9559f02bcc7d094ea37b9f03b10de2599ebbecf700c63ffd27fe28170347", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "db2fc4ab37f5dea6b62fd8b5321dbcf92f7e1ce690eab3346c0a143774fbccc3", + "start_line": 159, + "name": "socket", + "arity": 1 + }, + "socket_process?/1:77": { + "line": 77, + "guard": null, + "pattern": "pid", + "kind": "def", + "end_line": 78, + "ast_sha": "51e8720aae90202230e646a1e9f859b7ec69f2e9df38c474047a2d35d87efcef", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "b3a0cfe1b9b56ec63d700b8a6fa2ebbfa81c521116040ca548c31ab511b37044", + "start_line": 77, + "name": "socket_process?", + "arity": 1 + }, + "socket_process_dict/1:51": { + "line": 51, + "guard": null, + "pattern": "pid", + "kind": "defp", + "end_line": 59, + "ast_sha": "5a664c9d9babe772142eabb458fa697cc5878095f21dd2a4c2f37472c4267146", + "source_file": "lib/phoenix/debug.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", + "source_sha": "e22f7e231d9ebf00e69f3d2a7c790ef1c36e4730e5ffe9a5f439a842b967fe08", + "start_line": 51, + "name": "socket_process_dict", + "arity": 1 + } + }, + "Phoenix.Socket.V2.JSONSerializer": { + "byte_size!/3:145": { + "line": 145, + "guard": null, + "pattern": "bin, kind, max", + "kind": "defp", + "end_line": 156, + "ast_sha": "dcb2211b98f9fb0ca4f94d59dcd8a5c035794678e7532e561324e280810a724d", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "462b73fa8328b9d0f2ec2def5ed9997815901048c2bc9d718621bb516dd50b8d", + "start_line": 145, + "name": "byte_size!", + "arity": 3 + }, + "decode!/2:105": { + "line": 105, + "guard": null, + "pattern": "raw_message, opts", + "kind": "def", + "end_line": 108, + "ast_sha": "b5b36550af6e6cf8dd8b69961191d84f0b127fea5f062f9ef1745115d9a6a4b1", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "5f2b4329bc410d4146f86856c1f95fb44b3c5944efe04e08ce83f3ac49fbf81c", + "start_line": 105, + "name": "decode!", + "arity": 2 + }, + "decode_binary/1:124": { + "line": 124, + "guard": null, + "pattern": "<<0::integer-size(8), join_ref_size::integer-size(8), ref_size::integer-size(8),\n topic_size::integer-size(8), event_size::integer-size(8), join_ref::binary-size(join_ref_size),\n ref::binary-size(ref_size), topic::binary-size(topic_size), event::binary-size(event_size),\n data::binary>>", + "kind": "defp", + "end_line": 141, + "ast_sha": "2e28f5660f50dcecd6bfd0ae4e582169d2f9ca5143d311c489493b0ab8c7a14c", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "1648a4c908a36e570caed93cf53ac89d87af1dece63736aebb6f91383d8bfebd", + "start_line": 124, + "name": "decode_binary", + "arity": 1 + }, + "decode_text/1:112": { + "line": 112, + "guard": null, + "pattern": "raw_message", + "kind": "defp", + "end_line": 120, + "ast_sha": "eb5f8319d36ed3d2a7578f8b279fa49038333c143d3bf06b0cbf8429d1984107", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "e161fffae7ef749e1bbdff31b4c3ec988db00ef442faae4cc633f4598f681610", + "start_line": 112, + "name": "decode_text", + "arity": 1 + }, + "encode!/1:100": { + "line": 100, + "guard": null, + "pattern": "%Phoenix.Socket.Message{payload: invalid}", + "kind": "def", + "end_line": 101, + "ast_sha": "992bf9ccc2a86c62f6695eefa135f662a161e74d92c2ea82a22c71a92c91ccaf", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "dbf7b3ea6746cc6ab4566d550ba38673d6adcfa0c18b24d759f55832f26a18f0", + "start_line": 100, + "name": "encode!", + "arity": 1 + }, + "encode!/1:38": { + "line": 38, + "guard": null, + "pattern": "%Phoenix.Socket.Reply{payload: {:binary, data}} = reply", + "kind": "def", + "end_line": 60, + "ast_sha": "8d784ee47fc52e3b2b1c3763dba52a034b0f0874d3a2f2001b8c0cbb5e0729cf", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "5ccabc0d2e3c48f79390507d5bdacc9f5f2cfe7a54070eba9cc0cebf93b88c21", + "start_line": 38, + "name": "encode!", + "arity": 1 + }, + "encode!/1:63": { + "line": 63, + "guard": null, + "pattern": "%Phoenix.Socket.Reply{} = reply", + "kind": "def", + "end_line": 72, + "ast_sha": "e9f97c2df76b3015ed9c51a610c973fb91022132a3a6df72d1cb5288b241fe1c", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "164f45776f4fb006dfab1e25c7bc1c290a45b982b295153b8d39e2953f745aba", + "start_line": 63, + "name": "encode!", + "arity": 1 + }, + "encode!/1:75": { + "line": 75, + "guard": null, + "pattern": "%Phoenix.Socket.Message{payload: {:binary, data}} = msg", + "kind": "def", + "end_line": 92, + "ast_sha": "0460918667c2fc73898b1838a7ea5d05090fd6977c4193f0a50a3f2f7b7d4dff", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "63049e138a7bf446e4641abf52e4911d9e17072b553da1ed9548fbbdfa49599b", + "start_line": 75, + "name": "encode!", + "arity": 1 + }, + "encode!/1:95": { + "line": 95, + "guard": null, + "pattern": "%Phoenix.Socket.Message{payload: %{}} = msg", + "kind": "def", + "end_line": 97, + "ast_sha": "a49db4bf7efa65286a482c84e5a94671decf73da4f6afd9d84a05839b37f719d", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "381150b7d5fc91a60bd54b4a7ef66849be6b911e30afda7c5583ca7e85238603", + "start_line": 95, + "name": "encode!", + "arity": 1 + }, + "fastlane!/1:12": { + "line": 12, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{payload: {:binary, data}} = msg", + "kind": "def", + "end_line": 25, + "ast_sha": "36e72cb0c91fd9ff4dca6de9a7129d39c37ab4afc0045df6cce53a9dd1d65d88", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "9a6abe26d05df78b930e0bf665e5420ed0d32dab241d0e9ce4e2e0e72f4fb478", + "start_line": 12, + "name": "fastlane!", + "arity": 1 + }, + "fastlane!/1:28": { + "line": 28, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{payload: %{}} = msg", + "kind": "def", + "end_line": 30, + "ast_sha": "e298c2e4121da571e5c7eb116790bddd8be8f1602f6d800b1a4360bdb38043b8", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "b8ff3519270248d9a343830ff81f37415db323049d53eed55a7bfc61db690435", + "start_line": 28, + "name": "fastlane!", + "arity": 1 + }, + "fastlane!/1:33": { + "line": 33, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{payload: invalid}", + "kind": "def", + "end_line": 34, + "ast_sha": "fdcf5996005faf80269f682ecb1237e5a894520bb3b7ddfc807dea14a986021f", + "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", + "source_sha": "de334dec22f7a4d0c1ad918ae21b8d98d3cb007a37fa34009f82f8cebc379bce", + "start_line": 33, + "name": "fastlane!", + "arity": 1 + } + }, + "Phoenix.MissingParamError": { + "__struct__/0:32": { + "line": 32, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 32, + "ast_sha": "c5d30ef2f9fbbaa5805526071857dbc9afac5c74ac46e170f7290957c8bdd5df", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", + "start_line": 32, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:32": { + "line": 32, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 32, + "ast_sha": "f3ca7d7758f206f046b9f7b4c9516bbf1c42697b88af43fddaecf08408e9bbfb", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", + "start_line": 32, + "name": "__struct__", + "arity": 1 + }, + "exception/1:34": { + "line": 34, + "guard": null, + "pattern": "[key: value]", + "kind": "def", + "end_line": 37, + "ast_sha": "bb13e0f73605fba6881169ef192e9d6ed239dfe21dddba659a91bcce73e523d3", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "9007b3b150c884086a2c45430c1d2601772eb998acbda7416c22776a7e2c3850", + "start_line": 34, + "name": "exception", + "arity": 1 + }, + "message/1:32": { + "line": 32, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 32, + "ast_sha": "090ff7a37a5f95b7f7f5e0beeb3a5d8b7a0970da0b4637aa7f983a246e238b20", + "source_file": "lib/phoenix/exceptions.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", + "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", + "start_line": 32, + "name": "message", + "arity": 1 + } + }, + "Inspect.Phoenix.Socket.Message": { + "__impl__/1:39": { + "line": 39, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 39, + "ast_sha": "61ddaabe83b7fa6d2d5b0325141cb78fe19864f80709190ab5362c655d893a64", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "b33a5b76c8e50806e8939064f73c6a0be1451dd778529947d59a057d8a841020", + "start_line": 39, + "name": "__impl__", + "arity": 1 + }, + "inspect/2:40": { + "line": 40, + "guard": null, + "pattern": "%Phoenix.Socket.Message{} = msg, opts", + "kind": "def", + "end_line": 42, + "ast_sha": "2be110e8204966ea6a90984b6d20a36abc8381042e84fd8a7ae2812b445d02fc", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "9c581032c7a5d6d07a2dc518882c43aeef93c0b461eaaa15e7c37756a9bb6ed5", + "start_line": 40, + "name": "inspect", + "arity": 2 + }, + "process_message/1:45": { + "line": 45, + "guard": "is_map(payload)", + "pattern": "%{payload: payload} = msg", + "kind": "defp", + "end_line": 46, + "ast_sha": "ffc6157b12e9b904dd4caedb0b89286a4bcbbfd58a9b4c5bd25e98a7f65ea09b", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "09bd5650a0df3c5c8ebb489201a8e42fbd7b5de9f0c0ade5d91bfa14675676ca", + "start_line": 45, + "name": "process_message", + "arity": 1 + }, + "process_message/1:49": { + "line": 49, + "guard": null, + "pattern": "msg", + "kind": "defp", + "end_line": 49, + "ast_sha": "26162abdc7663ac0db6566dec6a04f2e634b5f06a22cefe8bfac806a69c7f29c", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "09fb43158895c443864ffdfde12ddd6fb8c58852916639f39249dbe1a848e005", + "start_line": 49, + "name": "process_message", + "arity": 1 + } + }, + "Phoenix.CodeReloader": { + "call/2:112": { + "line": 112, + "guard": null, + "pattern": "conn, opts", + "kind": "def", + "end_line": 121, + "ast_sha": "92e88fa7f80980dc39d16a61760f927053201d3d75eadbb70f85550cac01869d", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "33870511f54712713ad2a20dc0d5ae84933a119e1653ff4836bcb519aa59f206", + "start_line": 112, + "name": "call", + "arity": 2 + }, + "child_spec/1:75": { + "line": 75, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 75, + "ast_sha": "157b79c877260fdec0ca9b487c797af86b212136d8251b8f8ca1332ed78a21a0", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "ea9cbc176c4b8022b128fa69fd9ac7c96b9b5a1dec5a91bab6fbbd7bbc5e0218", + "start_line": 75, + "name": "child_spec", + "arity": 1 + }, + "format_output/1:330": { + "line": 330, + "guard": null, + "pattern": "output", + "kind": "defp", + "end_line": 334, + "ast_sha": "43ad73a6516f2d2780398ef645ef39f7383717bf5c784a900a303a47f749a7c0", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "676174e47f3d7ee6421b82c6373fd465d602af749e86ad7591a51e16b0fe8dab", + "start_line": 330, + "name": "format_output", + "arity": 1 + }, + "init/1:105": { + "line": 105, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 106, + "ast_sha": "710c460cf431317dce006a40afd9c90eb207fd1057bf038cdaffd9d053e2555e", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "0a2bae7ff64ecc411e1cca12df9b09b3fb31e0f29a7d260293d227c4213fb33c", + "start_line": 105, + "name": "init", + "arity": 1 + }, + "reload!/2:63": { + "line": 63, + "guard": null, + "pattern": "endpoint, opts", + "kind": "def", + "end_line": 63, + "ast_sha": "89122a0d1ea41bd70f38d313ca8313c2167b6f669ce906ffb18e2e4c84321b0f", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "afec2cac81890b9f7f9ef578b3296a0740b9209b79664f897b8069c33c451a45", + "start_line": 63, + "name": "reload!", + "arity": 2 + }, + "reload/1:55": { + "line": 55, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 55, + "ast_sha": "949f861f8f9c5ce8c9445d3156fc7508624bd7c76bdd28025fabd0ed9cb6560d", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "5ae7da26c62cc4c740bc529f031e7e129b98fae25f8443528a095b597a4ce9b7", + "start_line": 55, + "name": "reload", + "arity": 1 + }, + "reload/2:55": { + "line": 55, + "guard": null, + "pattern": "endpoint, opts", + "kind": "def", + "end_line": 56, + "ast_sha": "5f09be9711c4170053f6916f97e23b7986f5b47ecb8903fb91f27c808e5543ab", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "be5e3b1058820908e5d4354a517630f83ba12d60612a9f3684c304bf9d24f431", + "start_line": 55, + "name": "reload", + "arity": 2 + }, + "remove_ansi_escapes/1:337": { + "line": 337, + "guard": null, + "pattern": "text", + "kind": "defp", + "end_line": 338, + "ast_sha": "41c59c6f30acdce644c743c2310bd2749ee8acab4facd7591d994ed06cebdfa1", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "982710449f8b70f798d04c8e51a78f2c363ca13ae4e605a5133ec4ab04b9f1cf", + "start_line": 337, + "name": "remove_ansi_escapes", + "arity": 1 + }, + "sync/0:71": { + "line": 71, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 71, + "ast_sha": "dacc0bf02a2c7f55b44ddcb27e22a206334997df6e7db58833aafe0c39748b73", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "b531ec1c8134ed7a6230e8b03459bc11453a4aab6a7064f6465dcd9a2920ddb7", + "start_line": 71, + "name": "sync", + "arity": 0 + }, + "template/1:125": { + "line": 125, + "guard": null, + "pattern": "output", + "kind": "defp", + "end_line": 323, + "ast_sha": "17b57f4a866b7982d8629e28b6670d3b5e429acdec0c3bd885ca7827e6494c9b", + "source_file": "lib/phoenix/code_reloader.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", + "source_sha": "63157a57556b7c0181ba31870aadb52209a3d20e080bc8b4d60fed53b8fa7140", + "start_line": 125, + "name": "template", + "arity": 1 + } + }, + "Phoenix.Socket.InvalidMessageError": { + "__struct__/0:254": { + "line": 254, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 254, + "ast_sha": "ea62c9d2410f46fd24e0e05e724e8607dcad2c1ec4d7c919dd53084b8a06e3af", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", + "start_line": 254, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:254": { + "line": 254, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 254, + "ast_sha": "edb0c33423262545a059c009c1de30c0614b36b9eadaedf9b78a7c407cefb581", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", + "start_line": 254, + "name": "__struct__", + "arity": 1 + }, + "exception/1:254": { + "line": 254, + "guard": "is_list(args)", + "pattern": "args", + "kind": "def", + "end_line": 254, + "ast_sha": "51af484f83a1353124d7d452c9158df456767cb18c090e7df4cfa3c66f5a1104", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", + "start_line": 254, + "name": "exception", + "arity": 1 + }, + "message/1:254": { + "line": 254, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 254, + "ast_sha": "021eb93373fbfda6c5362413dea869d354e8b9afb6b10aff6c711a896a51649b", + "source_file": "lib/phoenix/socket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", + "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", + "start_line": 254, + "name": "message", + "arity": 1 + } + }, + "Phoenix.Socket.V1.JSONSerializer": { + "decode!/2:30": { + "line": 30, + "guard": null, + "pattern": "message, _opts", + "kind": "def", + "end_line": 38, + "ast_sha": "f7c70d6459b39870de76064b9a1f87e3235c779efe142501ac2c9250a44fcbde", + "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_sha": "c9b87c2c0cff44f00c3edabded019a7eb8ed3b486fc36cd94fa014e1aa2a65c4", + "start_line": 30, + "name": "decode!", + "arity": 2 + }, + "encode!/1:14": { + "line": 14, + "guard": null, + "pattern": "%Phoenix.Socket.Reply{} = reply", + "kind": "def", + "end_line": 22, + "ast_sha": "cc0d77e763a0a9b4c82f3f4d6e1ac520ef4bb50c89b86bf3f145c8d38f435ff0", + "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_sha": "08726fa9def1d4845126e46caecbb6497cf02053c83eb5a8f9f7095d793e54b9", + "start_line": 14, + "name": "encode!", + "arity": 1 + }, + "encode!/1:25": { + "line": 25, + "guard": null, + "pattern": "%Phoenix.Socket.Message{} = map", + "kind": "def", + "end_line": 26, + "ast_sha": "3f74baa7b8cde19788cab08629e2e66e162a416ea99cee4ba1130ae0a4dcb4ae", + "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_sha": "9570c414e26c3c24803eafb6ef55605fbe18eec0a050fda2094d9a93ea69a9fd", + "start_line": 25, + "name": "encode!", + "arity": 1 + }, + "encode_v1_fields_only/1:42": { + "line": 42, + "guard": null, + "pattern": "%Phoenix.Socket.Message{} = msg", + "kind": "defp", + "end_line": 45, + "ast_sha": "e33449ad47b5627ff4471e9d85028552c54dccca51130f3c66241a4fc5a6d3ad", + "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_sha": "3fd46b2e7fe64f52df5587eb889af031da3c8b2ec06567291280c413cf5475fd", + "start_line": 42, + "name": "encode_v1_fields_only", + "arity": 1 + }, + "fastlane!/1:8": { + "line": 8, + "guard": null, + "pattern": "%Phoenix.Socket.Broadcast{} = msg", + "kind": "def", + "end_line": 10, + "ast_sha": "2dec9e4efe8c4968e9e6a9317e3e7e18292caaec62cfb80d826ef10534299d8c", + "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", + "source_sha": "b8a2e12c9975d4c62ea5fc1f05d58811c2554b12035aabb0723ee1a381141671", + "start_line": 8, + "name": "fastlane!", + "arity": 1 + } + }, + "Phoenix.Socket.Message": { + "__struct__/0:17": { + "line": 17, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 17, + "ast_sha": "3cd41b4fe8e17a5f901f4b6223067542c2e51491989c43924574d4e12923d25b", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "d6e0b680dc4c9b7890d7b131438caca2eebe76eecfadf9f1c8b855ac3a27461c", + "start_line": 17, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:17": { + "line": 17, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 17, + "ast_sha": "bcc70fed8a3e8988742eeefd236854846ef724aa920572ec68b07feffe42bea8", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "d6e0b680dc4c9b7890d7b131438caca2eebe76eecfadf9f1c8b855ac3a27461c", + "start_line": 17, + "name": "__struct__", + "arity": 1 + }, + "from_map!/1:24": { + "line": 24, + "guard": "is_map(map)", + "pattern": "map", + "kind": "def", + "end_line": 35, + "ast_sha": "fa9bc6a97967bfa479295132eb76e7e1db43017370d0cbe2465efe0b98125bce", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "22370285c52bf164b1784903f9dcc1f75b6a96aabd4989d897124574d51eb0f3", + "start_line": 24, + "name": "from_map!", + "arity": 1 + } + }, + "Phoenix.Controller.Pipeline": { + "__action_fallback__/2:39": { + "line": 39, + "guard": null, + "pattern": "plug, caller", + "kind": "def", + "end_line": 41, + "ast_sha": "06b208dc9082d2dc0a64e783a2df363704e113834865714b318ad77d3f6bf675", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "174cc72afeb9e0bef2eda88d64a89e4c41bf89851599b17f897616f5a9772a65", + "start_line": 39, + "name": "__action_fallback__", + "arity": 2 + }, + "__before_compile__/1:75": { + "line": 75, + "guard": null, + "pattern": "env", + "kind": "defmacro", + "end_line": 116, + "ast_sha": "445ced3dec7c256ad18f37d95e32c3a0db23f25fad11a00cdc0c509f9761a6e8", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "95c7b09f0bfe7685f8e64cfc64111f5d5c43ce690931ca64414e46a8b4ead5da", + "start_line": 75, + "name": "__before_compile__", + "arity": 1 + }, + "__catch__/5:144": { + "line": 144, + "guard": null, + "pattern": "%Plug.Conn{}, :function_clause, controller, action, [{controller, action, [%Plug.Conn{} | _] = action_args, _loc} | _] = stack", + "kind": "def", + "end_line": 152, + "ast_sha": "0098645acf12369cf6bf41ebeca20dd9764e898de5a04a137bd3685536043a81", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "396a962c0b53d109c257e22f2392d91a547611ea0fca59005f86a33974f37933", + "start_line": 144, + "name": "__catch__", + "arity": 5 + }, + "__catch__/5:155": { + "line": 155, + "guard": null, + "pattern": "%Plug.Conn{} = conn, reason, _controller, _action, stack", + "kind": "def", + "end_line": 156, + "ast_sha": "72c6902c211ccba529a35ba69669009fb642214bed65b9da816f6193892822de", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "e0f1e6b9f35878584f1f12e82f73ab13e3c2b1f4ded9246e846bd1dec666bad8", + "start_line": 155, + "name": "__catch__", + "arity": 5 + }, + "__using__/1:5": { + "line": 5, + "guard": null, + "pattern": "_", + "kind": "defmacro", + "end_line": 5, + "ast_sha": "7426f3e1666b6eae7333637eb833ccc34d19d04dab0f616763c7542c1ca0a2be", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "7076efa06766215d075f9a82942cbcf1918cb89191069441c724601520f5a5ac", + "start_line": 5, + "name": "__using__", + "arity": 1 + }, + "build_fallback/1:121": { + "line": 121, + "guard": null, + "pattern": ":unregistered", + "kind": "defp", + "end_line": 121, + "ast_sha": "7dd2b1626704645b197be5f3f960059b1486526b7cbc12030dba244d880d9782", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "6b59d0f73c96eae6c9fc7ef1cf77877f9f15e31c1cf5c7317e3c2364885beec3", + "start_line": 121, + "name": "build_fallback", + "arity": 1 + }, + "build_fallback/1:125": { + "line": 125, + "guard": null, + "pattern": "{:module, plug}", + "kind": "defp", + "end_line": 126, + "ast_sha": "cc37d4180da676123772e67ab1bb13f7dd4f0e8cde297cb96555a3c1dd54708b", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "56656ccd071c56605e086ab0b9b024866140fb35129e61494b1df6601ca44a0b", + "start_line": 125, + "name": "build_fallback", + "arity": 1 + }, + "build_fallback/1:134": { + "line": 134, + "guard": null, + "pattern": "{:function, plug}", + "kind": "defp", + "end_line": 138, + "ast_sha": "58516224be2319ec8825adb6a819a0301ce8c4d8533d8f67da4cbfc8c3af94f6", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "626b2438ebd1e5d65377e73673fafeeccc14d1d7c69ecd8d93071b09b2f8020f", + "start_line": 134, + "name": "build_fallback", + "arity": 1 + }, + "escape_guards/1:205": { + "line": 205, + "guard": "=:=(pre_expanded, :@) or =:=(pre_expanded, :__aliases__)", + "pattern": "{pre_expanded, _, [_ | _]} = node", + "kind": "defp", + "end_line": 207, + "ast_sha": "8db78fa2f8fcb33623cd917a6e6819a45508dc4f333f8571729f3a29f8b7e99b", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "65758547cc5402a8f7d4409f7a665a5f8621f8dd664d938455495cfd752685aa", + "start_line": 205, + "name": "escape_guards", + "arity": 1 + }, + "escape_guards/1:209": { + "line": 209, + "guard": null, + "pattern": "{left, meta, right}", + "kind": "defp", + "end_line": 210, + "ast_sha": "a9a003423e7b3d8dfae63b708be371801ecbb7c20d522d3c52b627530f7f4b7f", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "7ce51890dae6a9b2426781ba713f7b9235472e1c8fc04b721d27aec8efb48384", + "start_line": 209, + "name": "escape_guards", + "arity": 1 + }, + "escape_guards/1:212": { + "line": 212, + "guard": null, + "pattern": "{left, right}", + "kind": "defp", + "end_line": 213, + "ast_sha": "8a08af24b1bc38d6ffc5a025e1c1a7257fec8c9150abc5a487aa14dc3510122e", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "f91657d86544b740a93b125abbf0e419fab23082f54cbe6f4888e6344c716b67", + "start_line": 212, + "name": "escape_guards", + "arity": 1 + }, + "escape_guards/1:215": { + "line": 215, + "guard": null, + "pattern": "[_ | _] = list", + "kind": "defp", + "end_line": 216, + "ast_sha": "b674d6ee90093ec1834da802a22b591281abe81cb13a3f739c25902fe3f94771", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "ff77fedaf895ce6f82a2a36a0343071bd8a1da162a782009bd0380e861505713", + "start_line": 215, + "name": "escape_guards", + "arity": 1 + }, + "escape_guards/1:218": { + "line": 218, + "guard": null, + "pattern": "node", + "kind": "defp", + "end_line": 219, + "ast_sha": "9cecbc01864de67a1fd2e8ea65a41d43a1f4ebfcf6b72a419bb519b29fd6423c", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "b273eda3cb298f56cb2fe238629a7be04d2659cc29f5ea153e17be4b249ab1e0", + "start_line": 218, + "name": "escape_guards", + "arity": 1 + }, + "expand_alias/2:200": { + "line": 200, + "guard": null, + "pattern": "{:__aliases__, _, _} = alias, env", + "kind": "defp", + "end_line": 201, + "ast_sha": "7b31396c92d10375302e2d9bf348c3d9bb9889836f3d52344ee0111ec8719958", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "7599dd70b9a94c532aa4050ea2895b5b7ceb706318007c89ad50955b47a88598", + "start_line": 200, + "name": "expand_alias", + "arity": 2 + }, + "expand_alias/2:203": { + "line": 203, + "guard": null, + "pattern": "other, _env", + "kind": "defp", + "end_line": 203, + "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", + "start_line": 203, + "name": "expand_alias", + "arity": 2 + }, + "plug/1:164": { + "line": 164, + "guard": null, + "pattern": "{:when, _, [plug, guards]}", + "kind": "defmacro", + "end_line": 164, + "ast_sha": "88711d46faecc8f3fd49ef45f1a49b246cc6c67524f6f8aa05044073bcfc8575", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "bc70ae4a9260f827b1eec9027cf806b7c31eaea3150f727fa8c2a6ab14495c6d", + "start_line": 164, + "name": "plug", + "arity": 1 + }, + "plug/1:166": { + "line": 166, + "guard": null, + "pattern": "plug", + "kind": "defmacro", + "end_line": 166, + "ast_sha": "bac46bd8fd4b483bfea6f4dc6e920088432d73512521065d6952ad66a49a36d0", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "b2f60dac74b5c7502487d00505619f18657c433722f47671d5a2f2eed29ab9f4", + "start_line": 166, + "name": "plug", + "arity": 1 + }, + "plug/2:174": { + "line": 174, + "guard": null, + "pattern": "plug, {:when, _, [opts, guards]}", + "kind": "defmacro", + "end_line": 174, + "ast_sha": "80d383113c354e481627f9e1eed28f54c7e872eed310c02a3447d318a7643b72", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "6478f28b60eb5bff072305bcc94c958d50a8a3ded74dc02335ef9cf355099567", + "start_line": 174, + "name": "plug", + "arity": 2 + }, + "plug/2:176": { + "line": 176, + "guard": null, + "pattern": "plug, opts", + "kind": "defmacro", + "end_line": 176, + "ast_sha": "2c51455e139b9901eff58b87d1da70607a2c3cd6d3a0bb3e2ea6501487c4257d", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "cbc6c1ced5395f274350191bc318f472f0359bc7541a32a16913a07a9046a5f7", + "start_line": 176, + "name": "plug", + "arity": 2 + }, + "plug/4:178": { + "line": 178, + "guard": null, + "pattern": "plug, opts, guards, caller", + "kind": "defp", + "end_line": 196, + "ast_sha": "2d17d89bfc9b68521569670547cbc8b60b928bb9140ea7db060004622cc77509", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "7959fb9e6da8bb721d243c2fcad694585d26e0ace9c7ca9b568e85de1f2075f7", + "start_line": 178, + "name": "plug", + "arity": 4 + }, + "validate_fallback/3:51": { + "line": 51, + "guard": null, + "pattern": "plug, module, fallback", + "kind": "def", + "end_line": 69, + "ast_sha": "6e4dcf7def2250f4793dd91452c1a35f5a2b31501f12561ae26c124a6f747494", + "source_file": "lib/phoenix/controller/pipeline.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", + "source_sha": "2006e85d48cc9e4f32729e9459fcbcd3374129272687b20ffe29a3ccabc268b8", + "start_line": 51, + "name": "validate_fallback", + "arity": 3 + } + }, + "Mix.Tasks.Phx.Server": { + "iex_running?/0:39": { + "line": 39, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 40, + "ast_sha": "a8c0a92ccf3daaac170068d669439b90af0402053486f6b1335499cee7776f1b", + "source_file": "lib/mix/tasks/phx.server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "source_sha": "75d7f916f1bf0030e3de32da6d6e5c6cc1366596eefa58cd42f9d3f4723ae167", + "start_line": 39, + "name": "iex_running?", + "arity": 0 + }, + "open_args/1:43": { + "line": 43, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 48, + "ast_sha": "7410253064a1d200d713395b29e8503fa43733dd620ff35e578f264bff79e902", + "source_file": "lib/mix/tasks/phx.server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "source_sha": "1afe9b04c28fcf75d02f0514d50175a7463f0c16362eb29820a752a53220fdf4", + "start_line": 43, + "name": "open_args", + "arity": 1 + }, + "run/1:34": { + "line": 34, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 36, + "ast_sha": "8c3140247646c6d46700f7f532ec6593d60a72979d8c8f98c883198c5a3e93a1", + "source_file": "lib/mix/tasks/phx.server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "source_sha": "d58f8cc02ef2e1e11f7e6bb15bb1eb97bf275ceb8222fbc83ee638b747aef823", + "start_line": 34, + "name": "run", + "arity": 1 + }, + "run_args/0:52": { + "line": 52, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 53, + "ast_sha": "5560f88f28bc21a7607827f222bd5df115387f733ededd548b8451e2b03dabd1", + "source_file": "lib/mix/tasks/phx.server.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", + "source_sha": "60a441ba24d1e1f4048f52377c93aa98e2d68156c3b76704150687451b70c758", + "start_line": 52, + "name": "run_args", + "arity": 0 + } + }, + "Mix.Tasks.Phx.Routes": { + "app_mod/2:165": { + "line": 165, + "guard": null, + "pattern": "base, name", + "kind": "defp", + "end_line": 165, + "ast_sha": "37557354fe72d15282c69004b1b9a5baf4aa440576fe6e07d41e0107f5e0a95c", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "4dd2b75435a4120f3e53b665ea6db79457889a533bba886c49c1d52edc4ab8e9", + "start_line": 165, + "name": "app_mod", + "arity": 2 + }, + "endpoint/2:117": { + "line": 117, + "guard": null, + "pattern": "nil, base", + "kind": "defp", + "end_line": 118, + "ast_sha": "886e2a23ec167fbb0918e351a22d052f06203279f9bf25eb3223b0053922d469", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "4bc942765174f4e31b59fdf6bb2f59dec0a876e3176331dbfb7c84744bb12d3b", + "start_line": 117, + "name": "endpoint", + "arity": 2 + }, + "endpoint/2:121": { + "line": 121, + "guard": null, + "pattern": "module, _base", + "kind": "defp", + "end_line": 122, + "ast_sha": "0ef670ff48965f811438e4dcc513edb14701219ecd12ea0f17590a680c561676", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "2986a5a4ff76653483c105a03875a8d7d09ce8d92a617e8417501b25da3a9e46", + "start_line": 121, + "name": "endpoint", + "arity": 2 + }, + "get_file_path/1:169": { + "line": 169, + "guard": null, + "pattern": "module_name", + "kind": "defp", + "end_line": 172, + "ast_sha": "752b52144fd6709a783dfa6e11ca1da4937751a69ecae78fdf20a4d02fd383ca", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "d536479559305ed23ac403db2c92127f72a34ec97995a67f80d66470623939ac", + "start_line": 169, + "name": "get_file_path", + "arity": 1 + }, + "get_line_number/2:175": { + "line": 175, + "guard": null, + "pattern": "_, nil", + "kind": "defp", + "end_line": 175, + "ast_sha": "6b1d0d9d008c27a3962b992b4fe8cee78cae099b75857813966458a15418eb2f", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "9d0a78b70e73f4657bf480f6cbe1cde2944c01975a31ebe18d4ce2a766a69b23", + "start_line": 175, + "name": "get_line_number", + "arity": 2 + }, + "get_line_number/2:177": { + "line": 177, + "guard": null, + "pattern": "module, function_name", + "kind": "defp", + "end_line": 188, + "ast_sha": "52b001054fb2d1fe810dedb68ad28e608140b00ab9cbdcc5ab7ec288f269766f", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "60f256d625b7fe039f92875c37f42e3bbc672e6a1837f16c5639747500655ca1", + "start_line": 177, + "name": "get_line_number", + "arity": 2 + }, + "get_url_info/2:92": { + "line": 92, + "guard": null, + "pattern": "url, {router_mod, opts}", + "kind": "def", + "end_line": 113, + "ast_sha": "e4368964501f8ecad2761fb4febcc6d82414e6f4614b35ec9c5a9325842ad2cd", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "40b436c07c96680909f4c7a76e27867c0778e0e096874a4c07b7b01ef859c3f4", + "start_line": 92, + "name": "get_url_info", + "arity": 2 + }, + "loaded/1:161": { + "line": 161, + "guard": null, + "pattern": "module", + "kind": "defp", + "end_line": 162, + "ast_sha": "3cd38093fdcb501e0a4252b9e8ff5435bf897a46d4ce4d0fbba3b743a0d5c0e0", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "8683255157c8619929a7ee0d973f6fc57fecf9019b9ed3cddef3aba24a30816f", + "start_line": 161, + "name": "loaded", + "arity": 1 + }, + "router/2:125": { + "line": 125, + "guard": null, + "pattern": "nil, base", + "kind": "defp", + "end_line": 144, + "ast_sha": "71daa49abcfd41b3b786bc153fb3251e2ffbc9b5d737db540e1da2f09d53d678", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "10c9e8d983c83a90fed238c9648f0f154b28d712f633e69ef5f275e2be60c2b2", + "start_line": 125, + "name": "router", + "arity": 2 + }, + "router/2:156": { + "line": 156, + "guard": null, + "pattern": "router_name, _base", + "kind": "defp", + "end_line": 158, + "ast_sha": "9c1613ec19b41c543ee61dc754aecca1c9f172c2fb28ec610100562327681277", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "de7dc7fc8b0f0543d7c4b14f67f361397d7f9e0339f5d1828bce1f482226debe", + "start_line": 156, + "name": "router", + "arity": 2 + }, + "run/1:65": { + "line": 65, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 65, + "ast_sha": "e7d404e1fd06cc8abe98b523b47a30814ab7aaf77a4f5c131d192d64f8544aa0", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "09d8cf79b07f04b41f287c6fe1e8dd75d94448c458a9922a655414788597375f", + "start_line": 65, + "name": "run", + "arity": 1 + }, + "run/2:65": { + "line": 65, + "guard": null, + "pattern": "args, base", + "kind": "def", + "end_line": 88, + "ast_sha": "c8cabb09a8b612fba751cdf75814fab164fff9289c9802614a3ad47d0a7850d8", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "169ef3cd69be05ed4fcae3231ec88e3d3119fa83252ba771bc55ba95b8016040", + "start_line": 65, + "name": "run", + "arity": 2 + }, + "web_mod/2:167": { + "line": 167, + "guard": null, + "pattern": "base, name", + "kind": "defp", + "end_line": 167, + "ast_sha": "9ac8e17441e10b4d2d1c5d2be6f3869e112b755a4a080baccc317f20d8919bbe", + "source_file": "lib/mix/tasks/phx.routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", + "source_sha": "8cb627b5c416eb1b73c761fb6c7c360d6cc0b39d0b367b0a9041d555072de0fb", + "start_line": 167, + "name": "web_mod", + "arity": 2 + } + }, + "Phoenix.ConnTest": { + "receive_response/2:696": { + "line": 696, + "guard": null, + "pattern": "{:error, {_kind, exception, stack}}, expected_status", + "kind": "defp", + "end_line": 713, + "ast_sha": "79e3f022e2b2e6d75122e8e0d487ad0dc72ac5430202b8be8b2895bc08d6c1dd", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "f3aee01a761101e955a4b401988eda18d828068213ccdc03bc2ea7448b84f819", + "start_line": 696, + "name": "receive_response", + "arity": 2 + }, + "__using__/1:114": { + "line": 114, + "guard": null, + "pattern": "_", + "kind": "defmacro", + "end_line": 124, + "ast_sha": "a3e92c5a35eb9453f3df4dec848c74252ed719f3ef528cca852540330592555a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a45945ad30e4f52b120ce3682ce740a777f5294a187a464c172a864e0b71ad19", + "start_line": 114, + "name": "__using__", + "arity": 1 + }, + "response_content_type?/2:326": { + "line": 326, + "guard": null, + "pattern": "header, format", + "kind": "defp", + "end_line": 332, + "ast_sha": "132d0f2476d07e162d9fb548facdea83453a5c8829e640123ffaa6da3486b55e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "253a7e3a9d27e211f3cd03c94d30bd42f079ba295bb195cd8366abd47e0986a4", + "start_line": 326, + "name": "response_content_type?", + "arity": 2 + }, + "html_response/2:386": { + "line": 386, + "guard": null, + "pattern": "conn, status", + "kind": "def", + "end_line": 389, + "ast_sha": "1c6a53a532946535cc6a68f6e4a2da281202f232b4ae5acb7a0d7e49b57b888c", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "6206137662dd2c1eff7b52d52fbe1716281839f72479e01d89e2fe961a83bfb2", + "start_line": 386, + "name": "html_response", + "arity": 2 + }, + "dispatch/5:229": { + "line": 229, + "guard": null, + "pattern": "conn, _endpoint, method, _path_or_action, _params_or_body", + "kind": "def", + "end_line": 231, + "ast_sha": "b8e81a57ddaf2984668dc9e6d6369f6e8b7ea8d7bef8d59bd2506e1f667d082e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "ee5eff598d6afe532344ea3bc71160f57acb99e5cb119802e795b61f64be444e", + "start_line": 229, + "name": "dispatch", + "arity": 5 + }, + "options/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "92080e8dc91a68af87620f3d66bc4bdf34cb418b936fc606beafa93c2fbcf72c", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "options", + "arity": 3 + }, + "get_flash/1:278": { + "line": 278, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 278, + "ast_sha": "2b5f321f35bf1aba74655c8d2524a06c0ed0146d15fda852f9c9689e882a1b06", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "94b1f72a555a5e28d4ea6ca8b817bf06c55e0ea2c1044996fd944ebfe729be6d", + "start_line": 278, + "name": "get_flash", + "arity": 1 + }, + "clear_flash/1:299": { + "line": 299, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 299, + "ast_sha": "5adf712e3a1bd12dd2d479f90af75eb46b8b88d90761460d0dd688f637eedb11", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "ccb7dbfee3340489a3579f448b190ce40c124ee9b49c51130cfcc2d506225b1e", + "start_line": 299, + "name": "clear_flash", + "arity": 1 + }, + "patch/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "c4f9c759fa2f178280a93d6aba398a6bafa6a850978172e24f1ddf5103b32328", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "patch", + "arity": 2 + }, + "options/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "b686fccf3156c05de818fba622975fddcd6d93e4ed1ae240cda9b5b164c5ee98", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "options", + "arity": 2 + }, + "connect/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "dfc4f5f37485aeb486b8954a4147c2cfeecd5a2f5beb5811ae9380f7d77c160e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "connect", + "arity": 2 + }, + "connect/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "3e22c88bab40311012da8631985378150f2ecda9732f2e8e68f324810c5a2b17", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "connect", + "arity": 3 + }, + "put/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "a9bd6742d935df1da84558b49713a81b9e98899a597bcf8e81b7bf018a0e81bc", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "put", + "arity": 3 + }, + "text_response/2:401": { + "line": 401, + "guard": null, + "pattern": "conn, status", + "kind": "def", + "end_line": 404, + "ast_sha": "e581c1bdc26361090fd431eed08cd8be09e43226bc5d95c9d871ba33ad6bf951", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "206a9fb0c0b1ce49cd96425c2b4315b9b9fd500ac075e2c0670b2e86f26c5d2f", + "start_line": 401, + "name": "text_response", + "arity": 2 + }, + "get_flash/2:285": { + "line": 285, + "guard": null, + "pattern": "conn, key", + "kind": "def", + "end_line": 286, + "ast_sha": "376231054506fa49b8c0e652fd570cde9e2c65e489d357f73f16310fa4b1d9db", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "7b80de03329343f47c10a46f35df95e80a7d1190a3af0e838200c212d5510795", + "start_line": 285, + "name": "get_flash", + "arity": 2 + }, + "trace/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "4f755671eff6f86bb6bb14744f8fe89c1c8bc8df3aa6d2ece494f35bbdc2d249", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "trace", + "arity": 2 + }, + "recycle/2:476": { + "line": 476, + "guard": null, + "pattern": "conn, headers", + "kind": "def", + "end_line": 482, + "ast_sha": "49fa7fd9b378c8b5b60981dbc46acb70c0c600bead46abf3ab58201fc44648b5", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "5410c2068aee58546ea106e7c76dcdb79543fbf50b4d728dbcd3c77ce8da9c7c", + "start_line": 476, + "name": "recycle", + "arity": 2 + }, + "trace/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "767ac08c31c0390acafd6fcfd90c5362b38dc87eb0a315866475288fe65faa08", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "trace", + "arity": 3 + }, + "redirected_to/2:440": { + "line": 440, + "guard": null, + "pattern": "%Plug.Conn{state: :unset}, _status", + "kind": "def", + "end_line": 441, + "ast_sha": "3e20da8802702a243751e270986092180c708ff35dbdfa61236703d763df505f", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "26780908faedc7c7aa642a812126494afe3b15f6ae993752161a2ed67d77242a", + "start_line": 440, + "name": "redirected_to", + "arity": 2 + }, + "get/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "ae1cd704b6501b7ef30bf1f30765efd03efc9fb67715ac162acc970e294cb398", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "get", + "arity": 3 + }, + "redirected_params/2:590": { + "line": 590, + "guard": null, + "pattern": "%Plug.Conn{} = conn, status", + "kind": "def", + "end_line": 599, + "ast_sha": "1ffe1ca814e3829cbb0d5a27fc2a6a4a86c1282b62d47ebe2773f35b624062e6", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "ee0d61050867170340711af59cd895f6d5ea817e8d0ff56499c2153f600e7344", + "start_line": 590, + "name": "redirected_params", + "arity": 2 + }, + "patch/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "14da838412bcdc41be679905bab880636f571b5f9723174e2696b90400abe0a0", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "patch", + "arity": 3 + }, + "redirected_to/2:444": { + "line": 444, + "guard": "is_atom(status)", + "pattern": "conn, status", + "kind": "def", + "end_line": 445, + "ast_sha": "1192555a0c9a217eee278ccfc86539f384f9f5e66931ba587e0c8b7d914a365e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "f9332c26502a8cb2e626920904af2559501cb6f476c7bede5e7fac144cfe1892", + "start_line": 444, + "name": "redirected_to", + "arity": 2 + }, + "copy_headers/3:485": { + "line": 485, + "guard": null, + "pattern": "conn, headers, copy", + "kind": "defp", + "end_line": 487, + "ast_sha": "a7edebb6414559fc2d7db136c462909e95f39cc5ca9c2a317c2c0aa62214ceae", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "32fc28d540a05b5a5a41c200841f3c7187828f0880d05ecf2c6eb442922e1f71", + "start_line": 485, + "name": "copy_headers", + "arity": 3 + }, + "put_req_cookie/3:259": { + "line": 259, + "guard": null, + "pattern": "conn, key, value", + "kind": "def", + "end_line": 259, + "ast_sha": "54a871d9ee003764c3f7937b1a58b3815bffc1d499fb14fad64f33397379df0a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "6cfae39ed40985e161f4bdec639ca75024d967dcd2adf387f97ad67d0c1a4f34", + "start_line": 259, + "name": "put_req_cookie", + "arity": 3 + }, + "put/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "ceb30d6ec48925f6d943eabca79b3b56e1c8fc569dd2f3ac98a06773ab2d3dcb", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "put", + "arity": 2 + }, + "init_test_session/2:253": { + "line": 253, + "guard": null, + "pattern": "conn, session", + "kind": "def", + "end_line": 253, + "ast_sha": "38b57b7e9a6e02a69a55c7b069272883ab929d79843516537cb8b6328ad31c2d", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "dc9bc57ce33b405fbef42c82bd3efaa4f91979ba6ddef12b6f383cb9e84a10e8", + "start_line": 253, + "name": "init_test_session", + "arity": 2 + }, + "parse_content_type/1:337": { + "line": 337, + "guard": null, + "pattern": "header", + "kind": "defp", + "end_line": 341, + "ast_sha": "71069600c4d5fb75dbb931ee9277cea59e9f1c530526fb144cf778a9c243536f", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a019e34f386418dc6ed3394b74ca7f64395ecd215dc97ab621408ee4ef1fae67", + "start_line": 337, + "name": "parse_content_type", + "arity": 1 + }, + "build_conn/3:151": { + "line": 151, + "guard": null, + "pattern": "method, path, params_or_body", + "kind": "def", + "end_line": 154, + "ast_sha": "a34e6d69b6fcc46856ba1aba50c6e5b2aef8fb1b16295a55a602c4357c402877", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "05b989c814bef29a670f992e15770502064ed921ec163a077bc542af29b73a80", + "start_line": 151, + "name": "build_conn", + "arity": 3 + }, + "dispatch_endpoint/5:234": { + "line": 234, + "guard": "is_binary(path)", + "pattern": "conn, endpoint, method, path, params_or_body", + "kind": "defp", + "end_line": 237, + "ast_sha": "79d651952daf1b0bef18aa9dddd95aaae092db44c6ac80d9e20664f08185e26a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "f283b75d8359a1686204ed6d29b00a1fc10ca8af1c6563703400acdc8a176003", + "start_line": 234, + "name": "dispatch_endpoint", + "arity": 5 + }, + "redirected_params/1:590": { + "line": 590, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 590, + "ast_sha": "e41a95d0d2d9f7fd3281b9a37017c7b26d741ca78fa11f11bf3aae89a73eb6df", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "6331f6652fd69455a623e05ab625494872509bbed3c6d8b60887bd63f86b2c05", + "start_line": 590, + "name": "redirected_params", + "arity": 1 + }, + "redirected_to/2:453": { + "line": 453, + "guard": null, + "pattern": "conn, status", + "kind": "def", + "end_line": 454, + "ast_sha": "2428087f71914986ae61a89b24e0cfe91314b2974a353e505113a0bbecf9be96", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "dff4ac26fa938325f70eb349b8409ab67b5929bfcc84c15630bd2a9f58aa7330", + "start_line": 453, + "name": "redirected_to", + "arity": 2 + }, + "response/2:367": { + "line": 367, + "guard": null, + "pattern": "%Plug.Conn{status: status, resp_body: body}, given", + "kind": "def", + "end_line": 373, + "ast_sha": "ea0f9e9527684a6fdfb70f2d534ead2c81413265f90d2dc0a1f5955b57dad931", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "8e93c0d7e84753daff0c042a612d01ceed666e490bcc5b56f3c556f5da9f313a", + "start_line": 367, + "name": "response", + "arity": 2 + }, + "assert_error_sent/2:677": { + "line": 677, + "guard": null, + "pattern": "status_int_or_atom, func", + "kind": "def", + "end_line": 686, + "ast_sha": "672902839b6212675f55054b6864a8202a40702880dd459295720d47d49ca29e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "b6f06e175b634fd1acfe8df07845c47a7b55d42770d14a369b2552de7520c991", + "start_line": 677, + "name": "assert_error_sent", + "arity": 2 + }, + "json_response/2:418": { + "line": 418, + "guard": null, + "pattern": "conn, status", + "kind": "def", + "end_line": 422, + "ast_sha": "3da3a9c03189ed09afa68eb7255ca5c8d8bea84600d9b009fb85be5bee4ed75f", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "9e7e6cd5c20ac735b4ea80211d1afd2e022b5f240e1b620f42cb408bc25f773e", + "start_line": 418, + "name": "json_response", + "arity": 2 + }, + "build_conn/0:139": { + "line": 139, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 140, + "ast_sha": "df982030e955bfbd42afaee4910aa044748b8a3c3ca6ac021cf9aff149416364", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "7afc0de82194a551269b999229678d7046eb61addea7a341be2d2a9326b5a663", + "start_line": 139, + "name": "build_conn", + "arity": 0 + }, + "remove_script_name/3:603": { + "line": 603, + "guard": null, + "pattern": "conn, router, path", + "kind": "defp", + "end_line": 610, + "ast_sha": "6d9ddc3c8ec1e96bb56b84f25130537155c3b7bc11fbcff70026b6591f588f10", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "8ec6ff1eff0a389e93a2abb25f5ab0c00eabf6ecc074323fa378868d474c7fbd", + "start_line": 603, + "name": "remove_script_name", + "arity": 3 + }, + "bypass_through/3:572": { + "line": 572, + "guard": null, + "pattern": "conn, router, pipelines", + "kind": "def", + "end_line": 573, + "ast_sha": "7209434fd3993be5dd4e6dd234826772579b27bb45bc2946e2b1496bf7075496", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "7a50e9f4d5d3bb69c87376519055e1ac77c21bdada31a62626083695afb242c2", + "start_line": 572, + "name": "bypass_through", + "arity": 3 + }, + "receive_response/2:689": { + "line": 689, + "guard": null, + "pattern": "{:ok, conn}, expected_status", + "kind": "defp", + "end_line": 693, + "ast_sha": "b3176c12432ee3467a2543968eb7229f9107f65eb0c349a0bc31298d01975be9", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "dee345b1d903ebb77740139f6edcf4d1fec469fda7a086940549f01877b2e268", + "start_line": 689, + "name": "receive_response", + "arity": 2 + }, + "ensure_recycled/1:496": { + "line": 496, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 500, + "ast_sha": "b58388e2154c7042c95854ed2124228b075fc5d49fcea3ea858d4b0e4eed5afa", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c91d821de92003844682a328ebff906189cebe4809ad735853142de9486dc040", + "start_line": 496, + "name": "ensure_recycled", + "arity": 1 + }, + "post/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "b9fbd8b32626aaa1bfc2ce83a13bd7e588945351e47afb5051707eff3e726f25", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "post", + "arity": 2 + }, + "redirected_to/1:438": { + "line": 438, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 438, + "ast_sha": "09c4e56f659a52cf6619023051148f4dde87fe8414265d67eb36c3891a718b02", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "16fbf6ded5f6b33841c36ace7b0f95d50711a1093f4c28e5ed824dc1fac1788b", + "start_line": 438, + "name": "redirected_to", + "arity": 1 + }, + "discard_previously_sent/0:717": { + "line": 717, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 722, + "ast_sha": "992ff14de29814a12923368899964e863fd75ecd5fc6b76538b002e43440ba0a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "3deffad8fa1d3bd05f233468535967409dc5e3e870ed95b97a97560bbed5262e", + "start_line": 717, + "name": "discard_previously_sent", + "arity": 0 + }, + "bypass_through/2:562": { + "line": 562, + "guard": null, + "pattern": "conn, router", + "kind": "def", + "end_line": 563, + "ast_sha": "b1890afaa6654f47df7847e9e3352edc6a6d3733bc93123ceadedd1cdf3a1de8", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "5011004780881c6e4ee5efe85cad484b79004ed8d4ac682e0e9038b9e981dac2", + "start_line": 562, + "name": "bypass_through", + "arity": 2 + }, + "dispatch_endpoint/5:240": { + "line": 240, + "guard": "is_atom(action)", + "pattern": "conn, endpoint, method, action, params_or_body", + "kind": "defp", + "end_line": 243, + "ast_sha": "fc08eb02d2192ca7d43fdfeb9d416085f53a192caf0fd147284ad95949caccda", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "89f854d06f4b5a3edd49abe93d572a13cf186e381c6ceaa5e311bc7c43452943", + "start_line": 240, + "name": "dispatch_endpoint", + "arity": 5 + }, + "path_params/2:626": { + "line": 626, + "guard": "is_binary(to)", + "pattern": "%Plug.Conn{} = conn, to", + "kind": "def", + "end_line": 634, + "ast_sha": "7aa96d2fe9e6b4df8d6cc3d42274ce3aa8bde2b360851750e89daadc14859452", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "3cd914cfb73df5c2a8edd70b7a94aaf56be15a912e43be4a531abba473cad4a6", + "start_line": 626, + "name": "path_params", + "arity": 2 + }, + "response/2:357": { + "line": 357, + "guard": null, + "pattern": "%Plug.Conn{state: :unset}, _status", + "kind": "def", + "end_line": 358, + "ast_sha": "087fa9bfe00e13c184aea952ae2e6190d671d4c333b9c8a36e93f41c44d9bbee", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "776b864948251e7573e583d5b886941b3026be860d0fea31a20372d5c964dc2a", + "start_line": 357, + "name": "response", + "arity": 2 + }, + "put_flash/3:293": { + "line": 293, + "guard": null, + "pattern": "conn, key, value", + "kind": "def", + "end_line": 293, + "ast_sha": "0cc0d0e768353ec05ef8271d35cf425a2cae2c0cc2441c105763b3578b8dfd21", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "d1241bca377bd5908aa0098d4ab3a5d00921bfe761ff0d9d32e25a5c2652e4d2", + "start_line": 293, + "name": "put_flash", + "arity": 3 + }, + "head/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "900911b90a47ca57e041d0f0278092afd835f75a35f628195f56a4359d338e57", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "head", + "arity": 2 + }, + "delete_req_cookie/2:265": { + "line": 265, + "guard": null, + "pattern": "conn, key", + "kind": "def", + "end_line": 265, + "ast_sha": "ba2f663f7e9891c55c8c158dd7b9b320f751beb188f9fdf9c54860c0321373f1", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "883ba24a79b52d797d4d61660f2143dfe9e918362beca0f68451703cf7b273ec", + "start_line": 265, + "name": "delete_req_cookie", + "arity": 2 + }, + "recycle/1:476": { + "line": 476, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 476, + "ast_sha": "b2196471430cff8f5341f6f940093217dd5983b6a84c07b2eb64a1c9a76e99c0", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "956633e4ea0daf15d04337a2d47757e88c6744237fd518afcea0a9d4119108b0", + "start_line": 476, + "name": "recycle", + "arity": 1 + }, + "from_set_to_sent/1:246": { + "line": 246, + "guard": null, + "pattern": "%Plug.Conn{state: :set} = conn", + "kind": "defp", + "end_line": 246, + "ast_sha": "f36530cc3f368698810ed2457c3dd8cbb72a17f05d53d5ad67de135e042dd37f", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "32cdfe9535d07441e843cd7c2e445e66990b9380f0fe3f8fe17a9d6b14d5015f", + "start_line": 246, + "name": "from_set_to_sent", + "arity": 1 + }, + "from_set_to_sent/1:247": { + "line": 247, + "guard": null, + "pattern": "conn", + "kind": "defp", + "end_line": 247, + "ast_sha": "3788dcdb03297e0fc1a6cba16bc738d5200d64d9adf1d9a1d685c40a8e5a772e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c349254f30959dbc91231e7be27c8f7edefb0594e6014c00e55d2dcaec7e2041", + "start_line": 247, + "name": "from_set_to_sent", + "arity": 1 + }, + "get/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "0836d4eba6348894b50c21f418b6a7239af5ef6216dd028ce576db1aed130ddd", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "get", + "arity": 2 + }, + "fetch_flash/1:271": { + "line": 271, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 271, + "ast_sha": "590f1eafbde1a08cb81f0b83c3badacf6c7925d7702ae4596d4e3465a6c776db", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "7fb10f23f796d8eb8568cdd842e1822f113efaf74acc52b247a0c0cea704fd68", + "start_line": 271, + "name": "fetch_flash", + "arity": 1 + }, + "delete/2:165": { + "line": 165, + "guard": null, + "pattern": "x0, x1", + "kind": "defmacro", + "end_line": 165, + "ast_sha": "afd3ea3e7cf54a170e7e5c5ffa3da88f0be0d3fcd75f4414ff9670ed7ab28b0c", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", + "start_line": 165, + "name": "delete", + "arity": 2 + }, + "wrap_request/1:726": { + "line": 726, + "guard": null, + "pattern": "func", + "kind": "defp", + "end_line": 730, + "ast_sha": "ead6d5b6d3c82a1419ae8738573b02fba914d4fbcaaa56429c2b5ea648b73bfd", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a399bf47fb6e98906161ce632f7175595b11cd895dc8f94c994c70c5023086de", + "start_line": 726, + "name": "wrap_request", + "arity": 1 + }, + "head/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "a32cc12c340f81f30a6a43fde09034c0110edb5a2d10afce84e9264bd0ddc07a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "head", + "arity": 3 + }, + "redirected_to/2:448": { + "line": 448, + "guard": null, + "pattern": "%Plug.Conn{status: status} = conn, status", + "kind": "def", + "end_line": 450, + "ast_sha": "8610d780f599b3636eb11a6a5d2b4f65616e96a0e4dd8a16e7634bbefd403b0c", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "d1ae3a4ed63476af067967af12637c97faffc7e33c46016b32914387eaa71047", + "start_line": 448, + "name": "redirected_to", + "arity": 2 + }, + "delete/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "e6e83e96d96e88a1b5cd7e0ffa04d45dd7a3921c44ae676cec5e0b4e8880e986", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "delete", + "arity": 3 + }, + "build_conn/2:151": { + "line": 151, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 151, + "ast_sha": "859855eb91131699742d24fab4b72e052bdff5848f3ee04f3188ec50cdb3734a", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "6a25ff23aa1e2228d52f30000a43b44ea42778bbecad81c6c9d6162caa55ec01", + "start_line": 151, + "name": "build_conn", + "arity": 2 + }, + "post/3:165": { + "line": 165, + "guard": null, + "pattern": "conn, path_or_action, params_or_body", + "kind": "defmacro", + "end_line": 169, + "ast_sha": "163d1cb93c441eafa377f4c8031bb79b13c2a1c66c7c4b4df6f9ea4dd4e30c09", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", + "start_line": 165, + "name": "post", + "arity": 3 + }, + "bypass_through/1:552": { + "line": 552, + "guard": null, + "pattern": "conn", + "kind": "def", + "end_line": 553, + "ast_sha": "56eeb96838147dcab2914dd14766fcd189eaae3b851effd13382c9a9e70be010", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "e98c1a6d00ef37b05e20cadd7f2301a0f7fd5d14d795f151de189f0116fbc222", + "start_line": 552, + "name": "bypass_through", + "arity": 1 + }, + "response_content_type/2:311": { + "line": 311, + "guard": "is_atom(format)", + "pattern": "conn, format", + "kind": "def", + "end_line": 322, + "ast_sha": "6903f33c7f473c2a1e953888e7fdd986bdf8720775c398a76e7df890d7cb5c0b", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "a4c4c2882e49f971d5e1954afcff039c38370bc1046522876af9dac1a0d49841", + "start_line": 311, + "name": "response_content_type", + "arity": 2 + }, + "dispatch/5:213": { + "line": 213, + "guard": null, + "pattern": "%Plug.Conn{} = conn, endpoint, method, path_or_action, params_or_body", + "kind": "def", + "end_line": 227, + "ast_sha": "64137493c33df69d7b668a6417e88c4da7e99da5259db4dc08775a54569b240d", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "9dce62aa17c9dec56574b9eba86d54336d73467496e611a0dff956958f496bc2", + "start_line": 213, + "name": "dispatch", + "arity": 5 + }, + "dispatch/4:212": { + "line": 212, + "guard": null, + "pattern": "x0, x1, x2, x3", + "kind": "def", + "end_line": 212, + "ast_sha": "2ee3e0b32d5d8731143c61fc6b3668304b8e46ce3401485282a04e5bcd86c17e", + "source_file": "lib/phoenix/test/conn_test.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", + "source_sha": "5a1b97819c7a5cb46108b7e677a4fe6901e69906a7dbddcc085828161f038204", + "start_line": 212, + "name": "dispatch", + "arity": 4 + } + }, + "Mix.Tasks.Phx.Gen.Live": { + "context_files/1:205": { + "line": 205, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: true} = context", + "kind": "defp", + "end_line": 206, + "ast_sha": "5f2ea054a55c18bf6691946aee4cc547a71d9c92036791baa2f43daea35bb976", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", + "start_line": 205, + "name": "context_files", + "arity": 1 + }, + "context_files/1:209": { + "line": 209, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: false}", + "kind": "defp", + "end_line": 209, + "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", + "start_line": 209, + "name": "context_files", + "arity": 1 + }, + "copy_new_files/3:231": { + "line": 231, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", + "kind": "defp", + "end_line": 249, + "ast_sha": "ef458372fdc85f93b39ef098f57514add2bf4ec2c95bf1bf45e62bfb24119bef", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "7e321656048ee52e6b7becc0db32ab7ad8e497a999b2d2e1e488013e78c70008", + "start_line": 231, + "name": "copy_new_files", + "arity": 3 + }, + "default_options/1:423": { + "line": 423, + "guard": null, + "pattern": "{:array, :string}", + "kind": "defp", + "end_line": 424, + "ast_sha": "01549ffdfb83d7237a99f500b49ba21c9e00723d02db660bfa38d46a7648ff8f", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "f7baf8656ec69550ba797003cef4dbce49c50ef0b06cbbde34d1c7ec4a169d69", + "start_line": 423, + "name": "default_options", + "arity": 1 + }, + "default_options/1:426": { + "line": 426, + "guard": null, + "pattern": "{:array, :integer}", + "kind": "defp", + "end_line": 427, + "ast_sha": "ed3b02b5601a65b945fa5b81324b9a7cc04e437cd57b65d86235d1375131b558", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "0c6bc5b7c2583cc53321531782442ea51cc59459c6217490af281d5912293cc3", + "start_line": 426, + "name": "default_options", + "arity": 1 + }, + "default_options/1:429": { + "line": 429, + "guard": null, + "pattern": "{:array, _}", + "kind": "defp", + "end_line": 429, + "ast_sha": "5d58293c50e5eb42c1fc4cac63844c442b64a79f7acb29119153166f52272db3", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "71475429cbe803cbdb6e7877819a8eb755b00b60d50eb7ad2408348c028d0ed0", + "start_line": 429, + "name": "default_options", + "arity": 1 + }, + "do_inject_imports/4:268": { + "line": 268, + "guard": null, + "pattern": "context, file, file_path, inject", + "kind": "defp", + "end_line": 292, + "ast_sha": "bc49c06f149fcc7126cee6d33e6a79ca891495748c388452e481b405c0a2190a", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "3d35c7d82e3130216d8ac07044015a8941b5376dcc5c000c312c467de7fe1626", + "start_line": 268, + "name": "do_inject_imports", + "arity": 4 + }, + "files_to_be_generated/1:213": { + "line": 213, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", + "kind": "defp", + "end_line": 227, + "ast_sha": "47bc34bc7579a220d7f84945270bbb51d8741ea712576e8bfdcad2bd3db43fd7", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "1886d6dce8289e5b04b8bcdb13734db76d4382eca995f56c6d045d2470771ef0", + "start_line": 213, + "name": "files_to_be_generated", + "arity": 1 + }, + "inputs/1:362": { + "line": 362, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{} = schema", + "kind": "def", + "end_line": 419, + "ast_sha": "c0508df42c676b0d989bc346b291eeb3730dbf8fa66f15b7104cd11430c8d39f", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "16bf2a246cd580e79693583ef3182c772c4ed7b235e48bc392610554461f5a30", + "start_line": 362, + "name": "inputs", + "arity": 1 + }, + "label/1:431": { + "line": 431, + "guard": null, + "pattern": "key", + "kind": "defp", + "end_line": 431, + "ast_sha": "889b010b2220ae9186063009d2692c759aa9e861d5245e59485d14d5778faef0", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "a298472558e596e1e6ef15fbde1f3acc423119bdc3f18e26b72461c14e3fb8ac", + "start_line": 431, + "name": "label", + "arity": 1 + }, + "live_route_instructions/1:344": { + "line": 344, + "guard": null, + "pattern": "schema", + "kind": "defp", + "end_line": 357, + "ast_sha": "7ac87ecf56c783ca3b73b2ec7841eca84c4581c5ff22a77ada8d163bb71c94de", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "df86314d5fc4aed4008fd82ac57ab1fa13c70af17a8a0d2f85e6b5db829ea657", + "start_line": 344, + "name": "live_route_instructions", + "arity": 1 + }, + "maybe_inject_imports/1:252": { + "line": 252, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context", + "kind": "defp", + "end_line": 265, + "ast_sha": "893562d15a731f2e8e237bb565300eade49d4147d854407a7bd113f33457bf83", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "1b389cfb0fee2bb36dfc359c5b2354383c4ae6cec6478c2bb27e566a1a17bd9a", + "start_line": 252, + "name": "maybe_inject_imports", + "arity": 1 + }, + "maybe_print_upgrade_info/0:333": { + "line": 333, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 335, + "ast_sha": "f941d1e26061670ade00666c89adfc33b8656e08acb63827fa9e5781c99ad13b", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "29a2bd45c141787a57c4dac7965243266d2b0c8e857726fbe2cfa972020de7f8", + "start_line": 333, + "name": "maybe_print_upgrade_info", + "arity": 0 + }, + "print_shell_instructions/1:298": { + "line": 298, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", + "kind": "def", + "end_line": 330, + "ast_sha": "43e4c8bd46517a0de59197f62b97358d199dee7d4b9bf2222c2abd6cff717e6e", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "3e7fe3b9fd570b62c3c4a85bd720c07d5dfab1c4cdc6ed274d0d0682af2c4511", + "start_line": 298, + "name": "print_shell_instructions", + "arity": 1 + }, + "prompt_for_conflicts/1:198": { + "line": 198, + "guard": null, + "pattern": "context", + "kind": "defp", + "end_line": 202, + "ast_sha": "eed4c4b6928808d3b0ea8df4fd6fc5719a50afffc25b83062d346fa1085f214e", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "90bb78b802f638a452de361d55b4ad7f730fbc458b81fbed27efc49236a0c1d1", + "start_line": 198, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "run/1:125": { + "line": 125, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 183, + "ast_sha": "a0c4a9081924c67341013e75a40c4d3c630e683a5131bd2fb4f544d28130b4ac", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "6fb0c840fbb88d87dbf5c94c2bb3758a7a5f8b6dfaf8e278b00ab9c3d9002193", + "start_line": 125, + "name": "run", + "arity": 1 + }, + "scope_assign_route_prefix/1:445": { + "line": 445, + "guard": "not (route_prefix == nil)", + "pattern": "%{scope: %{route_prefix: route_prefix, assign_key: assign_key}} = schema", + "kind": "defp", + "end_line": 449, + "ast_sha": "8a88c4f9c977171ebf0cbd13a52843c55651c658d3077f2c9f62d6a7e9073dcb", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "247e983a0169c88f62cf9b99c16687f4771d0a3659a130b699eb8f10bd06326e", + "start_line": 445, + "name": "scope_assign_route_prefix", + "arity": 1 + }, + "scope_assign_route_prefix/1:452": { + "line": 452, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 452, + "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "e9a8e972479e20da74d9b8d9fdd7cc2007152cc11ee0fa7b7a4a1cc6cfadb0e4", + "start_line": 452, + "name": "scope_assign_route_prefix", + "arity": 1 + }, + "scope_param/1:433": { + "line": 433, + "guard": null, + "pattern": "%{scope: nil}", + "kind": "defp", + "end_line": 433, + "ast_sha": "0be4c98bc8c1e055676e5a164eaaacb027d03702091223bbf75a9e27f4aa8795", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "27adea72f54f4b0e00095bef7ae227bd9cfabe5f3009b12cf87ccadb4ed6e002", + "start_line": 433, + "name": "scope_param", + "arity": 1 + }, + "scope_param/1:435": { + "line": 435, + "guard": "not (route_prefix == nil)", + "pattern": "%{scope: %{route_prefix: route_prefix}}", + "kind": "defp", + "end_line": 435, + "ast_sha": "aa77a89cc1ef0f17c564b906a75bec4f9b509ef34c06db50210d8c0705529ee4", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "862bb69c196baa455ac9334092b391773ac8241a59e12a065ace2200d1536bc8", + "start_line": 435, + "name": "scope_param", + "arity": 1 + }, + "scope_param/1:438": { + "line": 438, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 438, + "ast_sha": "497083a97bb860901989df1d222da8cc59bf4c62eb142c3433474d9684adbfca", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "d1a1da2da764c388940eb0310d71b11cac2a5fd8fa4e31bb78ec0c586c06039d", + "start_line": 438, + "name": "scope_param", + "arity": 1 + }, + "scope_param_prefix/1:440": { + "line": 440, + "guard": null, + "pattern": "schema", + "kind": "defp", + "end_line": 442, + "ast_sha": "368a2faa97c5cc645a1751bd4c73ac483508e4bc3f413602df5d6a348e5e5ab1", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "e3b8234b7d2e03353273189b705d8ea379fc4d1bc6f310ecaeaa04def2c8a3fc", + "start_line": 440, + "name": "scope_param_prefix", + "arity": 1 + }, + "validate_context!/1:186": { + "line": 186, + "guard": null, + "pattern": "context", + "kind": "defp", + "end_line": 193, + "ast_sha": "c8d1e632ebbaba71dd69af9f4da61bb4069e07b89d116e5837ad797da4714d78", + "source_file": "lib/mix/tasks/phx.gen.live.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", + "source_sha": "6e597180007873e0ebfd89192015eec3837a13876913600d6902f99323b85438", + "start_line": 186, + "name": "validate_context!", + "arity": 1 + } + }, + "Phoenix.Socket.Broadcast": { + "__struct__/0:84": { + "line": 84, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 84, + "ast_sha": "156adac11563e1a8f578a01d8a26fa032010a48c84b4d26c93143a00186e2738", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "b8bd420528f6722df63c2785b86107c2fb928254c8dae3cfbe76fe618d95f51f", + "start_line": 84, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:84": { + "line": 84, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 84, + "ast_sha": "775d883c8c56ecb795debc1e86a37715a620259650ac2cd75c0122b9534dcdd0", + "source_file": "lib/phoenix/socket/message.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", + "source_sha": "b8bd420528f6722df63c2785b86107c2fb928254c8dae3cfbe76fe618d95f51f", + "start_line": 84, + "name": "__struct__", + "arity": 1 + } + }, + "Phoenix.Router.MalformedURIError": { + "__struct__/0:25": { + "line": 25, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 25, + "ast_sha": "1995670eccc62103070573c9956ac8bf5b66cad97d35b091c937cae2e4c1858b", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", + "start_line": 25, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:25": { + "line": 25, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 25, + "ast_sha": "78960ef9666aee750ea3e22daf0571a84be562627f5c880deb952d66f9df8297", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", + "start_line": 25, + "name": "__struct__", + "arity": 1 + }, + "exception/1:25": { + "line": 25, + "guard": "is_list(args)", + "pattern": "args", + "kind": "def", + "end_line": 25, + "ast_sha": "4b9ff8a2b73be1d8afbfa7e43d23622808281016f0ef3fa0e4c003e0a488b6c1", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", + "start_line": 25, + "name": "exception", + "arity": 1 + }, + "message/1:25": { + "line": 25, + "guard": null, + "pattern": "exception", + "kind": "def", + "end_line": 25, + "ast_sha": "707ecb09aaff0ee9cf0991ddad1f393af3d1429519d16aedb4a77cc182fb7637", + "source_file": "lib/phoenix/router.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", + "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", + "start_line": 25, + "name": "message", + "arity": 1 + } + }, + "Phoenix.Presence.Tracker": { + "child_spec/1:429": { + "line": 429, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 429, + "ast_sha": "dd8bad510a2c0064f75eb786c2e8dcef2350096f03f38b5c13bd2be76e7787f1", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "7c2592ee4bdddc1bef6cded482f11ff7073499e053972177ce3cb4b40acf8709", + "start_line": 429, + "name": "child_spec", + "arity": 1 + }, + "handle_diff/2:446": { + "line": 446, + "guard": null, + "pattern": "diff, state", + "kind": "def", + "end_line": 446, + "ast_sha": "29bbc10541053251eeb0801e793c9f08e045d5ca2857a38874c3fe3e4a9455ae", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "11391e4cedab663bc63eeef18881db4a75b61aab534e1e8a57a280db5fc83f2d", + "start_line": 446, + "name": "handle_diff", + "arity": 2 + }, + "handle_info/2:448": { + "line": 448, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 449, + "ast_sha": "1e971145cf281f0672c4653cd8ff9881790479a129e4120535b9d71c06e2d506", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "d8a0aa9c36017f3f1e5d1edb99722b00ba766ffddb87aac114d4311f1d3a95e0", + "start_line": 448, + "name": "handle_info", + "arity": 2 + }, + "init/1:444": { + "line": 444, + "guard": null, + "pattern": "state", + "kind": "def", + "end_line": 444, + "ast_sha": "7a36a23f05cedbcf26bb944bf48aa0ce6c8c97b26c181da656dfa546b23eba60", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "a6d1863ed96cdab255c9006443eb22e75783101ad94fb44e263147efbff70712", + "start_line": 444, + "name": "init", + "arity": 1 + }, + "start_link/1:431": { + "line": 431, + "guard": null, + "pattern": "{module, task_supervisor, opts}", + "kind": "def", + "end_line": 440, + "ast_sha": "113c212c16be2e0e4355d4a0a7dfd25bcc505e945df6300fb9bd7138549284d5", + "source_file": "lib/phoenix/presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", + "source_sha": "4ffd914f52b257c23d675e72fcfe2f56800751718d0761231195416196816945", + "start_line": 431, + "name": "start_link", + "arity": 1 + } + }, + "Phoenix.Transports.WebSocket": { + "call/2:39": { + "line": 39, + "guard": null, + "pattern": "%{method: \"GET\"} = conn, {endpoint, handler, opts}", + "kind": "def", + "end_line": 90, + "ast_sha": "0a15e260925731abb5ce90f85e455c8a6a316609c4aec968567bda6902688a27", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "827630ef1271620693c5a30b33a1c42654160facaa7b9346f812533590b091c9", + "start_line": 39, + "name": "call", + "arity": 2 + }, + "call/2:95": { + "line": 95, + "guard": null, + "pattern": "conn, _", + "kind": "def", + "end_line": 95, + "ast_sha": "6a270d60667739174b1e69d7ac7189ae374deee047bcec0ebb914c355d279ed6", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "92126c569a2587d2a9f84ded3a5b68fcbf66713bacaa03e9e93ac68884fccaf8", + "start_line": 95, + "name": "call", + "arity": 2 + }, + "default_config/0:26": { + "line": 26, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 30, + "ast_sha": "83052cd1c678de25649b63ac27aba74840220e65d65e019fadcaac5d5a2a4e19", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "3c9bfe7919906cbd660ccd0ded6185b8e16a1a87c6dabffcb420a6a4cd6e572d", + "start_line": 26, + "name": "default_config", + "arity": 0 + }, + "handle_error/2:97": { + "line": 97, + "guard": null, + "pattern": "conn, _reason", + "kind": "def", + "end_line": 97, + "ast_sha": "9d1681ce259b6a5cbb150f58a5264cf52b5c4136f750c3540699f45685ece77e", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "fa5cba5745f812200aac32656c95c4c47bab21b037c96f41ee0a3f347890a346", + "start_line": 97, + "name": "handle_error", + "arity": 2 + }, + "init/1:37": { + "line": 37, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 37, + "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", + "start_line": 37, + "name": "init", + "arity": 1 + }, + "maybe_auth_token_from_header/2:124": { + "line": 124, + "guard": null, + "pattern": "conn, _", + "kind": "defp", + "end_line": 124, + "ast_sha": "d418dff67505cf526abe380616091b9f20a1537b40a9770ff5b9292092c7c786", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "3465c5df608942102ca5a8d5c47d36aefaa005f81aec552c3d646fd73d7b2083", + "start_line": 124, + "name": "maybe_auth_token_from_header", + "arity": 2 + }, + "maybe_auth_token_from_header/2:99": { + "line": 99, + "guard": null, + "pattern": "conn, true", + "kind": "defp", + "end_line": 119, + "ast_sha": "ccc15490e332cb39f21dbdf9b6a7ab974ff0ab2aa146cf0dbde9414a60594fc2", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "f17cead75132a04ead67742ae47efd76a42ffa336f84ea619de4b40a84d52f6a", + "start_line": 99, + "name": "maybe_auth_token_from_header", + "arity": 2 + }, + "set_actual_subprotocols/2:126": { + "line": 126, + "guard": null, + "pattern": "conn, []", + "kind": "defp", + "end_line": 126, + "ast_sha": "fb0b120244e528cf45ff61ee9d3985833c2ecba61f0a1b9a95a02dc13c117d56", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "6208875b938e8f18095ea00efc2beab293839cf73a585d5b9607ec4c159f0d56", + "start_line": 126, + "name": "set_actual_subprotocols", + "arity": 2 + }, + "set_actual_subprotocols/2:128": { + "line": 128, + "guard": null, + "pattern": "conn, subprotocols", + "kind": "defp", + "end_line": 129, + "ast_sha": "2ab885da31271956d17e500cd1acef636a5c26beb24a97cc194ab84c4a336187", + "source_file": "lib/phoenix/transports/websocket.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", + "source_sha": "8ec5f911f96d10bd8de0cd08455a3a228eab2c74c88fdd0153faf3e17bbe9dad", + "start_line": 128, + "name": "set_actual_subprotocols", + "arity": 2 + } + }, + "Phoenix.Router.ConsoleFormatter": { + "calculate_column_widths/3:77": { + "line": 77, + "guard": null, + "pattern": "router, routes, endpoint", + "kind": "defp", + "end_line": 100, + "ast_sha": "aec1da2c1b6748fe59c5f21c929df28231eaf7b6ecc392b81088dfd08128b854", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "2f43d0506fc25a16c6c13e23ef58f23067914540caa574efe479545bb0f5d1e5", + "start_line": 77, + "name": "calculate_column_widths", + "arity": 3 + }, + "format/1:12": { + "line": 12, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 12, + "ast_sha": "5af33b378f1f21a99ac116d91626253061a0e6ba95e39831050e57a436339612", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "70396ac6ba0a2122ba78b616f9c9ec55489ec5f930a955099e25cbca78413784", + "start_line": 12, + "name": "format", + "arity": 1 + }, + "format/2:12": { + "line": 12, + "guard": null, + "pattern": "router, endpoint", + "kind": "def", + "end_line": 19, + "ast_sha": "090087836f4eb40e4107331afca6df08e4d1d6cf6747bab27c9a73037ae11657", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "eb2232582c0e7e89dbd37311d4f5e368f7e6c8f3de4d53e1c8e072cd2b6e557b", + "start_line": 12, + "name": "format", + "arity": 2 + }, + "format_endpoint/2:23": { + "line": 23, + "guard": null, + "pattern": "nil, _router", + "kind": "defp", + "end_line": 23, + "ast_sha": "8408127f0731978d264d59589cdd10837665f4be0dfa5c1483b585b17e9440a8", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "40ad14e36e58e60336ba16ee991bef6683d6847ed8d2f33552dc6a13ef0b6e63", + "start_line": 23, + "name": "format_endpoint", + "arity": 2 + }, + "format_endpoint/2:25": { + "line": 25, + "guard": null, + "pattern": "endpoint, widths", + "kind": "defp", + "end_line": 32, + "ast_sha": "8b4a7700b74d1e588dbe5a9a68de53b1293ce39d97ad9ea207ed29029000c6b5", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "53c67f2399dd6f80124abf777d72e29fbbc0cafaa5fe02d9e7b8553d0f01d226", + "start_line": 25, + "name": "format_endpoint", + "arity": 2 + }, + "format_longpoll/2:56": { + "line": 56, + "guard": null, + "pattern": "{_path, Phoenix.LiveReloader.Socket, _opts}, _", + "kind": "defp", + "end_line": 56, + "ast_sha": "face257af3ebbc42e806ad0770ff8f34342ab8228c9d189390700deff2d6c13a", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "d737e11b6662c1aed161c252c26b846dedc5c90d60f982c56281b30a35528157", + "start_line": 56, + "name": "format_longpoll", + "arity": 2 + }, + "format_longpoll/2:58": { + "line": 58, + "guard": null, + "pattern": "{path, module, opts}, widths", + "kind": "defp", + "end_line": 69, + "ast_sha": "2a2beb6495878cf35ac12240c2c33cef438e6c6833672163ea97ddaaf53775fa", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "4d3a1903371d9d9883342b3bcb5a0463cbb6c178af43d91771dc5e0dea65a338", + "start_line": 58, + "name": "format_longpoll", + "arity": 2 + }, + "format_route/3:104": { + "line": 104, + "guard": null, + "pattern": "route, router, column_widths", + "kind": "defp", + "end_line": 121, + "ast_sha": "b09742e4a69f5e9d04b850079014283abcb573d36b7fbd90d373e20914a845ed", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "7638108e96505b4ff9ff42c662890b7a4b5eef4a83556bcae2205754222d867d", + "start_line": 104, + "name": "format_route", + "arity": 3 + }, + "format_websocket/2:37": { + "line": 37, + "guard": null, + "pattern": "{_path, Phoenix.LiveReloader.Socket, _opts}, _", + "kind": "defp", + "end_line": 37, + "ast_sha": "face257af3ebbc42e806ad0770ff8f34342ab8228c9d189390700deff2d6c13a", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "c8df5492218d801aa9d23cddea0d467050e992dc6ab3eb50c10692555b557e49", + "start_line": 37, + "name": "format_websocket", + "arity": 2 + }, + "format_websocket/2:39": { + "line": 39, + "guard": null, + "pattern": "{path, module, opts}, widths", + "kind": "defp", + "end_line": 49, + "ast_sha": "0274c297479c3e3bef168059823e5e36b4b771182e1e910e5ec2178caac827fd", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "bf71d7f2545206d788fd7f3ad01cac7bb4f5289b56cf811cd9992072b2a6d9c6", + "start_line": 39, + "name": "format_websocket", + "arity": 2 + }, + "route_name/2:124": { + "line": 124, + "guard": null, + "pattern": "_router, nil", + "kind": "defp", + "end_line": 124, + "ast_sha": "60abc151cae31791e25de9995207ac349d4ae572866d128be3356466394a3f70", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "0a7ac060514ce09d9ce4c4009da71f864bc72056d03f66b4f9865b57a59ac1d8", + "start_line": 124, + "name": "route_name", + "arity": 2 + }, + "route_name/2:126": { + "line": 126, + "guard": null, + "pattern": "router, name", + "kind": "defp", + "end_line": 128, + "ast_sha": "06c8031304f8ccf793bffab7a61e7077598f1e9277893ecfa0cdc0585c646369", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "09cf474f92fd938acde9f17c4812bcdca471434914d8561575a354535b472cf5", + "start_line": 126, + "name": "route_name", + "arity": 2 + }, + "socket_verbs/1:136": { + "line": 136, + "guard": null, + "pattern": "socket_opts", + "kind": "defp", + "end_line": 138, + "ast_sha": "e2a37f4a18bd0010d59c53a7b3212ba0bf59276a2435135fde7f872be92ee378", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "603bbf52e30f5b6f80c3042c68d0440ce8c04bad4ba8d000d252f27195a875a0", + "start_line": 136, + "name": "socket_verbs", + "arity": 1 + }, + "verb_name/1:134": { + "line": 134, + "guard": null, + "pattern": "verb", + "kind": "defp", + "end_line": 134, + "ast_sha": "c68e9299fbe0a332ddba555cf27404f278bdbd3789ac7d6a293fde6117b6fd61", + "source_file": "lib/phoenix/router/console_formatter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", + "source_sha": "b239d199b3f59562bcab913f0a6d5146da196417e3ab1dce971a015418f74134", + "start_line": 134, + "name": "verb_name", + "arity": 1 + } + }, + "Mix.Tasks.Compile.Phoenix": { + "mix_recompile?/1:50": { + "line": 50, + "guard": null, + "pattern": "_mod", + "kind": "defp", + "end_line": 50, + "ast_sha": "e20ff36bc6ae5df7fcd9a1f2ed37aa52443b52baa566570f40e65f26faed982f", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "811f47d371c7816b4abd68bd5406a908daea722fad36abc24dd9838b37185a56", + "start_line": 50, + "name": "mix_recompile?", + "arity": 1 + }, + "modules_for_recompilation/1:38": { + "line": 38, + "guard": null, + "pattern": "modules", + "kind": "defp", + "end_line": 40, + "ast_sha": "e7870f4941654f6f092da4da00f7ef1b7236dfe08ee645d7f00ceb4d0ad6347e", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "9b0ae2e369c0e835c66720c844b795122b4002fd6a89bad2b858327148821205", + "start_line": 38, + "name": "modules_for_recompilation", + "arity": 1 + }, + "modules_to_file_paths/1:57": { + "line": 57, + "guard": null, + "pattern": "modules", + "kind": "defp", + "end_line": 58, + "ast_sha": "cd1666fd661e68e3add2a11aab7bcf165326be395095b29c5b5013080b75b3c1", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "915440c11b29165b78fbf4bb3dd63d8e0ee9481cc72afe75a70a520acf26d2ed", + "start_line": 57, + "name": "modules_to_file_paths", + "arity": 1 + }, + "phoenix_recompile?/1:44": { + "line": 44, + "guard": null, + "pattern": "mod", + "kind": "defp", + "end_line": 45, + "ast_sha": "8c8703096ef346e9c3909f2508d70870922cd8cbf95d514e3127dde3f5bf4cf3", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "97a58d04e700c3f41957eb4e32760c591a96b89b0def263bd518a207347a839d", + "start_line": 44, + "name": "phoenix_recompile?", + "arity": 1 + }, + "run/1:7": { + "line": 7, + "guard": null, + "pattern": "_args", + "kind": "def", + "end_line": 20, + "ast_sha": "2cee42aa2fdbf0088dbeef1810a6d64a458e2249683db65696e4f0a1b84ab533", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "40d0eebfc7cc617d8811a9fdfa744b571810cd4c5a024301897fbc39d3ebc76a", + "start_line": 7, + "name": "run", + "arity": 1 + }, + "touch/0:25": { + "line": 25, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 31, + "ast_sha": "9e6b026c5ecbad5f7b484befc838b2c849a27969467a0dde9e0761dfcb255ce3", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "316426f471654ddb35ddb509c588d512eef4cb0601bdc7383396765101d3adb1", + "start_line": 25, + "name": "touch", + "arity": 0 + }, + "touch_if_exists/1:34": { + "line": 34, + "guard": null, + "pattern": "path", + "kind": "defp", + "end_line": 35, + "ast_sha": "69e3feb9701a886bf45aac2a010be95b5d9af59df8a02845d4497676c70bd637", + "source_file": "lib/mix/tasks/compile.phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", + "source_sha": "39cd1cf2ec483f90a507e1ad2bad520b3bacd759acefa589bf18716affcb55df", + "start_line": 34, + "name": "touch_if_exists", + "arity": 1 + } + }, + "Phoenix.Socket.PoolSupervisor": { + "init/1:47": { + "line": 47, + "guard": null, + "pattern": "{endpoint, name, partitions}", + "kind": "def", + "end_line": 62, + "ast_sha": "2eccc13dd2d0f794d84364366a195b60aa038dc7bca368d9cecf51e942127aee", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "7c768896594767c13a01bc0b0f75667fb465853fd5b19e0f08ca0ce89b6ea509", + "start_line": 47, + "name": "init", + "arity": 1 + }, + "start_child/3:13": { + "line": 13, + "guard": null, + "pattern": "socket, key, spec", + "kind": "def", + "end_line": 28, + "ast_sha": "344efca6c6807486464459777bfc8559b213d005a26170697c2375c8e3de7ee2", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "1c5de7f797c0791bfb8d9729c963a0c6069ac54c3f2fd87ef356906c97962eb3", + "start_line": 13, + "name": "start_child", + "arity": 3 + }, + "start_link/1:5": { + "line": 5, + "guard": null, + "pattern": "{endpoint, name, partitions}", + "kind": "def", + "end_line": 9, + "ast_sha": "48e1287a703e08a9153182f7f54d2d8cb0fd38063313d2af3c3b20a6a79b8f57", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "807528c15450b22deb1f4e0626bb2faea75d8563f79b68f775a6ca5e479cef91", + "start_line": 5, + "name": "start_link", + "arity": 1 + }, + "start_pooled/2:35": { + "line": 35, + "guard": null, + "pattern": "ref, i", + "kind": "def", + "end_line": 42, + "ast_sha": "1546691fe11f3b629eceacd2ffec3115a41455b125428f358f4969257a9da234", + "source_file": "lib/phoenix/socket/pool_supervisor.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", + "source_sha": "6e2f6ec62959fbd39dee234f03caa17e80d89f06cd942d544e75cbbded16d9c0", + "start_line": 35, + "name": "start_pooled", + "arity": 2 + } + }, + "Phoenix.Endpoint.Cowboy2Adapter": { + "bound_address/2:124": { + "line": 124, + "guard": null, + "pattern": "scheme, ref", + "kind": "defp", + "end_line": 133, + "ast_sha": "255310bb4df745862fff94de63f3e6718d641f093eb85a805c51810797106487", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "453a675260f9e3d6fb046a68a0d0008eb8c6afb8a98a085e44486351bb7327d6", + "start_line": 124, + "name": "bound_address", + "arity": 2 + }, + "child_spec/4:78": { + "line": 78, + "guard": null, + "pattern": "scheme, endpoint, config, code_reloader?", + "kind": "defp", + "end_line": 94, + "ast_sha": "b8750c336fd5e28e19a551ebd16236503967bb51ef49b832bcc5d46f880259d2", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "c9c206fd22b0d6006573838c7c1f77c42cdbe8bc670174f5570acf65ab40d945", + "start_line": 78, + "name": "child_spec", + "arity": 4 + }, + "child_specs/2:52": { + "line": 52, + "guard": null, + "pattern": "endpoint, config", + "kind": "def", + "end_line": 74, + "ast_sha": "78253e80169b5989c553d98634f4616394852bf75840cc482d32dd2142d1c677", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "225074ee7a0da3b2132b26401c093bac23b5912193b18486e06910f419a11f95", + "start_line": 52, + "name": "child_specs", + "arity": 2 + }, + "info/3:119": { + "line": 119, + "guard": null, + "pattern": "scheme, endpoint, ref", + "kind": "defp", + "end_line": 121, + "ast_sha": "4b8c0268606d670655152de350f19b11968e65041ba8c4e18614a10c669e205e", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "feab93e109ef16cd5c05e4b00dc85b413f63ab43db5e465e705dafe5814d87b5", + "start_line": 119, + "name": "info", + "arity": 3 + }, + "make_ref/2:152": { + "line": 152, + "guard": null, + "pattern": "endpoint, scheme", + "kind": "defp", + "end_line": 153, + "ast_sha": "79bc3643c7fd8dd4d706aa450d2740e237297686222f8cc5a47bd58403532c65", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "fb193c09b79d7d823be1b1955985e330897dcf4f178e2aefa4909c7f04e84b8b", + "start_line": 152, + "name": "make_ref", + "arity": 2 + }, + "port_to_integer/1:137": { + "line": 137, + "guard": null, + "pattern": "{:system, env_var}", + "kind": "defp", + "end_line": 137, + "ast_sha": "56256b11f3e682bb249a1b10fbfe8a3ba26c3de02162d251d830016cdb9607bf", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "e3b91863e72be67bb9de16a0e26ee4de2d7463cc3e0d6b7c8756591f0b7fe557", + "start_line": 137, + "name": "port_to_integer", + "arity": 1 + }, + "port_to_integer/1:138": { + "line": 138, + "guard": "is_binary(port)", + "pattern": "port", + "kind": "defp", + "end_line": 138, + "ast_sha": "59f40fcfaab0be4d79d4c1262798dbadf3a66b838f129ad50b3d4b67eb9b6062", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "506fdff094b92b11c5e6bdcbb576f85d8a5503d1d0084c38d965017cec596895", + "start_line": 138, + "name": "port_to_integer", + "arity": 1 + }, + "port_to_integer/1:139": { + "line": 139, + "guard": "is_integer(port)", + "pattern": "port", + "kind": "defp", + "end_line": 139, + "ast_sha": "cad919fd626581b0483f841c270b6d53496d670660994359c8a795e10ec403e8", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "074f5f04a25e914d778ae0d21b26d1a362468488bf8979abbc0bab9ad5878c46", + "start_line": 139, + "name": "port_to_integer", + "arity": 1 + }, + "server_info/2:141": { + "line": 141, + "guard": null, + "pattern": "endpoint, scheme", + "kind": "def", + "end_line": 149, + "ast_sha": "380e78a30a2c429140329237c35331ec45cecf3c89488fee75b04a6fead9629d", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "0f48bb659398cc7ba7bc0dbe9c8d106f005f58ba8f20a9b46e4f7f60384c702d", + "start_line": 141, + "name": "server_info", + "arity": 2 + }, + "start_link/3:98": { + "line": 98, + "guard": null, + "pattern": "scheme, endpoint, {m, f, [ref | _] = a}", + "kind": "def", + "end_line": 115, + "ast_sha": "ee44f569956f7afaaedc65f424901da5ff54b72eb61a07cb400f8ea7391cc1d2", + "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", + "source_sha": "029e1b82d5f7d2066becfe5979dbe10dcd6e946296d7df620c79a3170660b4ed", + "start_line": 98, + "name": "start_link", + "arity": 3 + } + }, + "Phoenix.Config": { + "cache/3:47": { + "line": 47, + "guard": null, + "pattern": "module, key, fun", + "kind": "def", + "end_line": 70, + "ast_sha": "4ae0a15b366b42172fab73dcb0f3dfdaeab6dfbe599046541a5d6ffc28f2170f", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "a28135ff0dac401645803316f449984b2d77cc220b0d6a99ba7158bd7e933e3f", + "start_line": 47, + "name": "cache", + "arity": 3 + }, + "child_spec/1:9": { + "line": 9, + "guard": null, + "pattern": "init_arg", + "kind": "def", + "end_line": 862, + "ast_sha": "baca25a2936ae666e1588466e4be9983f98391425239c1c34af22dae49d3fda0", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", + "start_line": 9, + "name": "child_spec", + "arity": 1 + }, + "clear_cache/1:79": { + "line": 79, + "guard": null, + "pattern": "module", + "kind": "def", + "end_line": 80, + "ast_sha": "f62a681e6eedeb02c004f34e58d5245bdfbbbe6c0d071da7733357286fa8c53c", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "8b7968d783f9090eaf2d7f9aeeb06bf75f17d48ffca6c3d6e9637f772683b21b", + "start_line": 79, + "name": "clear_cache", + "arity": 1 + }, + "code_change/3:9": { + "line": 9, + "guard": null, + "pattern": "_old, state, _extra", + "kind": "def", + "end_line": 940, + "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", + "start_line": 9, + "name": "code_change", + "arity": 3 + }, + "config_change/3:125": { + "line": 125, + "guard": null, + "pattern": "module, changed, removed", + "kind": "def", + "end_line": 127, + "ast_sha": "dbb5b06cb65da1cfcc2ed48bd4cd7da2fe783b90897419116e0311e709e238ba", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "d8b4a603baa3686ab3d5059bdaa2ae97ca272d3627595c63bca0b5f492cd016e", + "start_line": 125, + "name": "config_change", + "arity": 3 + }, + "fetch_config/2:95": { + "line": 95, + "guard": null, + "pattern": "otp_app, module", + "kind": "defp", + "end_line": 98, + "ast_sha": "e555df1e55141495ea9d4308624f0a4188cc25cf1eb362a5ca09a589540ffe16", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "e0e0af8b771298afbc8d518e28d7605e691f4e63071046cf55833ee957cc7c7b", + "start_line": 95, + "name": "fetch_config", + "arity": 2 + }, + "from_env/3:89": { + "line": 89, + "guard": null, + "pattern": "otp_app, module, defaults", + "kind": "def", + "end_line": 92, + "ast_sha": "c799eafbacaae207f1bac2e7d6f1d854c94e0e79d6800136babcbde2651c8d7a", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "b6b1d74f2db1b482e6d4515e56d072a22f1fe910343e544209fd2a17163adc47", + "start_line": 89, + "name": "from_env", + "arity": 3 + }, + "handle_call/3:139": { + "line": 139, + "guard": null, + "pattern": "{:permanent, key, value}, _from, {module, permanent}", + "kind": "def", + "end_line": 141, + "ast_sha": "d65edab8003fd9cfba645c009d499fa4d05e8c6dc156a1892613e9dfbd72e9fd", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "365eb856b4d2df908a61a1879dfa4ab27d6a8df34d88b537c8d7978a42b65e0c", + "start_line": 139, + "name": "handle_call", + "arity": 3 + }, + "handle_call/3:144": { + "line": 144, + "guard": null, + "pattern": "{:config_change, changed, removed}, _from, {module, permanent}", + "kind": "def", + "end_line": 155, + "ast_sha": "f7e1ac8b242a061a4c39aa0cc2335e81182048d1d8f8a95e8bb8751771931a8a", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "7c6520cdd464e23c67bbf328d5299157c9d2631cfe08b3a324b2713afa204375", + "start_line": 144, + "name": "handle_call", + "arity": 3 + }, + "handle_cast/2:9": { + "line": 9, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 929, + "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", + "start_line": 9, + "name": "handle_cast", + "arity": 2 + }, + "handle_info/2:9": { + "line": 9, + "guard": null, + "pattern": "msg, state", + "kind": "def", + "end_line": 912, + "ast_sha": "9c213083de9b6ab3f0679b07483924f7b187f2d0f2b0dae897415a75953f4d28", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", + "start_line": 9, + "name": "handle_info", + "arity": 2 + }, + "init/1:132": { + "line": 132, + "guard": null, + "pattern": "{module, config, permanent}", + "kind": "def", + "end_line": 136, + "ast_sha": "8ac7eef74b3b3ed348c189690d5cbda6b0a024a287c60d2be00a5658f1f0d472", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "69fbcbf7eac502ba5f7a63d156ad1bc9e5b986fa54aeeabf3e1c44ccb41d06d2", + "start_line": 132, + "name": "init", + "arity": 1 + }, + "merge/2:107": { + "line": 107, + "guard": null, + "pattern": "a, b", + "kind": "def", + "end_line": 107, + "ast_sha": "4984be24b24549bfaef520fc7082d24a8efcf845da01b5e89e7ae07067f060a2", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "ef77f12058cdb0519534e19d6935d056be80dd6e20859a30b8870b991f1b2b16", + "start_line": 107, + "name": "merge", + "arity": 2 + }, + "merger/3:109": { + "line": 109, + "guard": null, + "pattern": "_k, v1, v2", + "kind": "defp", + "end_line": 113, + "ast_sha": "eecd488011b611aa57f27d0bd994653448b2af6dd1e87cfe50a1cc004cc8d874", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "4033a289590825017d910a431c58b2d9c8d105a294f4c029e575c00a7c70fbc3", + "start_line": 109, + "name": "merger", + "arity": 3 + }, + "permanent/3:31": { + "line": 31, + "guard": null, + "pattern": "module, key, value", + "kind": "def", + "end_line": 33, + "ast_sha": "7691502b07f0feba884226086f779ec33f99831e286e503b75b0386e6cb140a8", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "1c7dac28d112ed47850aea1142633c1fa38a5657597d4bbd19cdab3035ebc90d", + "start_line": 31, + "name": "permanent", + "arity": 3 + }, + "put/3:22": { + "line": 22, + "guard": null, + "pattern": "module, key, value", + "kind": "def", + "end_line": 23, + "ast_sha": "de8a33b251daeb68279201cbb58bbf8f0e90a0c1f8a35f1e99daaba5a59c2fce", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "ad999f365b8ef9d2ee1a78ac8e6d63aa0a7207c760c47a0e969ba43627341639", + "start_line": 22, + "name": "put", + "arity": 3 + }, + "start_link/1:14": { + "line": 14, + "guard": null, + "pattern": "{module, config, defaults, opts}", + "kind": "def", + "end_line": 16, + "ast_sha": "009aa6cfde605c5fb8a23b03420b6b2ac186e227a5d577bf3b6c3a08efd01755", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "50b0bdfd8ab7f8816e38a0e478f45b9e6520132aab0e3cf360f1eec9973b6e48", + "start_line": 14, + "name": "start_link", + "arity": 1 + }, + "terminate/2:9": { + "line": 9, + "guard": null, + "pattern": "_reason, _state", + "kind": "def", + "end_line": 9, + "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", + "start_line": 9, + "name": "terminate", + "arity": 2 + }, + "update/3:159": { + "line": 159, + "guard": null, + "pattern": "module, config, permanent", + "kind": "defp", + "end_line": 164, + "ast_sha": "5133593182d5ee60090590d5d10ba79ea7772cbfd2108be313dc04f23ac09509", + "source_file": "lib/phoenix/config.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", + "source_sha": "152ceaef6ea831b0e25eac6cacef66d8974a6c8fb0bd173949306f63e4788905", + "start_line": 159, + "name": "update", + "arity": 3 + } + }, + "Phoenix.Digester": { + "clean/3:335": { + "line": 335, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 335, + "ast_sha": "0c1328aac1bb2e7f32612dcc651603dc49c89768b123f060ae2226a7ac6fc0db", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "67f6c4a3c899cb544971d5c3fa74bc235d56ac225073525be2db4a093c2a1720", + "start_line": 335, + "name": "clean", + "arity": 3 + }, + "remove_compressed_files/2:407": { + "line": 407, + "guard": null, + "pattern": "files, output_path", + "kind": "defp", + "end_line": 408, + "ast_sha": "f043e0e18f446eb876f10822e2d06198b839905a4ec42fee1bfaa1e2ed23c4a1", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "c8fb1951f0ffa96efeb39e3bc1f995e391c3a0a99e020f6670bf651d4e6074d7", + "start_line": 407, + "name": "remove_compressed_files", + "arity": 2 + }, + "load_manifest/1:87": { + "line": 87, + "guard": null, + "pattern": "output_path", + "kind": "defp", + "end_line": 96, + "ast_sha": "4760bc3b46bfb51a610bd61917724fb5bb7fdbc66c51a27b6969a4e57f4d9877", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "6c1c505408797ae6c5fe303e8d50c13c08a10c0587e9176a647cd8c9cff2f7c3", + "start_line": 87, + "name": "load_manifest", + "arity": 1 + }, + "relative_digested_path/1:311": { + "line": 311, + "guard": null, + "pattern": "digested_path", + "kind": "defp", + "end_line": 312, + "ast_sha": "b1b2c29b9c37ee550dbf942caa28a7dbda4e39e3def5f76b139355714460391b", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "71d2f933496549c4521d5484a01f9cbb507b8390671b872093c41dcd859ee464", + "start_line": 311, + "name": "relative_digested_path", + "arity": 1 + }, + "now/0:9": { + "line": 9, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 10, + "ast_sha": "a426216498e6b24c3d6a23c4f6597027abcf5deac7a14c40478e0f26009bb3b3", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "f33b643ca894a657098ca15f0038929f5ac19e06df9c7927e4de60ffa1c3a1d2", + "start_line": 9, + "name": "now", + "arity": 0 + }, + "files_to_clean/4:376": { + "line": 376, + "guard": null, + "pattern": "latest, digests, max_age, keep", + "kind": "defp", + "end_line": 381, + "ast_sha": "f93dde3b33b316e116ef03234aabb10f6632608027ff515245f6086ac6f2e22a", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "27b1c2a900ffcb02f43bf5ded7fd16969b07a44872172dbf3f16ad9912bdb284", + "start_line": 376, + "name": "files_to_clean", + "arity": 4 + }, + "clean/4:335": { + "line": 335, + "guard": null, + "pattern": "path, age, keep, now", + "kind": "def", + "end_line": 340, + "ast_sha": "91ecea3a056b18698f86e2ea3d47ce7a1c0e4ae451142a4d91bcfc953484a181", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "3e67bd5e164be62771f28023494619d9cc685639059851ad0778a6b8028b5a86", + "start_line": 335, + "name": "clean", + "arity": 4 + }, + "digested_contents/3:230": { + "line": 230, + "guard": null, + "pattern": "file, latest, with_vsn?", + "kind": "defp", + "end_line": 241, + "ast_sha": "78d8ed2602de116168ade4017cd09fe48baeeabfa4be5599278dac8b78df4f4f", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "882be5181d527129923e3e8471f2178a53ad7e7d9cbf66825545ef0d8645927f", + "start_line": 230, + "name": "digested_contents", + "arity": 3 + }, + "remove_manifest/1:130": { + "line": 130, + "guard": null, + "pattern": "output_path", + "kind": "defp", + "end_line": 131, + "ast_sha": "9b0e99327022bc6bc5d3d6130db9c259cf3a67daeaaeecee08e19930ff2e0fdf", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "595ae3f0e242baf50e9085f78e9900c8a15034eb6c05bab8187374a41b3145bf", + "start_line": 130, + "name": "remove_manifest", + "arity": 1 + }, + "generate_digests/1:134": { + "line": 134, + "guard": null, + "pattern": "files", + "kind": "defp", + "end_line": 139, + "ast_sha": "d619f570606f46c41230888004c46a9841c49894ab341b637560c4427867dd33", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "57af9379235ef3b71f9b89a202437bdabb4fb8a452fc9e66f4c63e1a0244cbc6", + "start_line": 134, + "name": "generate_digests", + "arity": 1 + }, + "manifest_join/2:155": { + "line": 155, + "guard": null, + "pattern": "path, filename", + "kind": "defp", + "end_line": 155, + "ast_sha": "db85de8a3c10a413ce2950ea6bae6f30ab8c4885cc7c2dd0b470725b7d8a9a23", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "e9ae6ec8f1e51cd3f538f6e32ba2f21589d6468b37cc78deaea0106da33f4742", + "start_line": 155, + "name": "manifest_join", + "arity": 2 + }, + "filter_files/1:40": { + "line": 40, + "guard": null, + "pattern": "input_path", + "kind": "defp", + "end_line": 45, + "ast_sha": "468ac66da9d0ebea8a27d94b0e9e9916e92d85a966b2b411f2e63755eef54f97", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "2c380c648d3fe6e53c04c0847fcbc5f0c42b6dca2d3baaa3e087dabc1df2cd0b", + "start_line": 40, + "name": "filter_files", + "arity": 1 + }, + "fixup_sourcemaps/1:48": { + "line": 48, + "guard": "is_list(files)", + "pattern": "files", + "kind": "defp", + "end_line": 49, + "ast_sha": "8e2ab9e8a01416cab7920e04888f93dbb55548a374c9a35612eba5de2f44e927", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "0621c00a15718cc8bddf15c38b885b221e7e515142a3cd3a5356ebd56c7a454a", + "start_line": 48, + "name": "fixup_sourcemaps", + "arity": 1 + }, + "compile/3:20": { + "line": 20, + "guard": null, + "pattern": "input_path, output_path, with_vsn?", + "kind": "def", + "end_line": 34, + "ast_sha": "65f9e83690728cfd0d2bf84e9a8e08c977d0bfe3642ccb26a17c1b988d394d8c", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "7bc18e0675bf81ab4b7d1f17f5d4dcaa30bb7dbdd8f23613c384406fb205852c", + "start_line": 20, + "name": "compile", + "arity": 3 + }, + "write_manifest/3:115": { + "line": 115, + "guard": null, + "pattern": "latest, digests, output_path", + "kind": "defp", + "end_line": 127, + "ast_sha": "74f4e619a7344890da47f17e9dfcc4543e6851834d29a5cafa0d681299c363fb", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "4d0d9ee505495ae786cfb42c5d1542f4a6ecf2d3495fcfa85090282d89f8d737", + "start_line": 115, + "name": "write_manifest", + "arity": 3 + }, + "absolute_digested_url/3:317": { + "line": 317, + "guard": null, + "pattern": "url, digested_path, false", + "kind": "defp", + "end_line": 318, + "ast_sha": "1b99ee0fb078b936756c2ce3cd87220def54a5d585e83e630c430f315021661d", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "0d151b9abaff0c26e5f5cf7b638e05c8726ef6298861a5846702c7e127b369a5", + "start_line": 317, + "name": "absolute_digested_url", + "arity": 3 + }, + "maybe_fixup_sourcemap/2:52": { + "line": 52, + "guard": null, + "pattern": "sourcemap, files", + "kind": "defp", + "end_line": 56, + "ast_sha": "0a518bf03348d10b9a2e46af19609068c26465521cb8dda53c476af6900fc05a", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "238698ee9e5845a8f26e0fcebc34d8df62b6207aaa1ef78dce7982cc8f17ee30", + "start_line": 52, + "name": "maybe_fixup_sourcemap", + "arity": 2 + }, + "versions_to_clean/3:384": { + "line": 384, + "guard": null, + "pattern": "versions, max_age, keep", + "kind": "defp", + "end_line": 390, + "ast_sha": "c2b036ba94c21c67ebcda3358fa143ac81d507ae35b1510121866b719539de85", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "cfd61297bf61418d64124285c3b1951477de6e3b1377022b57479fc360a4d205", + "start_line": 384, + "name": "versions_to_clean", + "arity": 3 + }, + "fixup_sourcemap/2:60": { + "line": 60, + "guard": null, + "pattern": "%{} = sourcemap, files", + "kind": "defp", + "end_line": 68, + "ast_sha": "227cdf68a5c2948ede46aaaf80e884ee518d02a18a6b2e2fc56a3406fb639f04", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "881f54bdf33cd3efa0ff6c82ac047e9b904533d830957be8da21d81b90bc0e27", + "start_line": 60, + "name": "fixup_sourcemap", + "arity": 2 + }, + "compressed_extensions/0:165": { + "line": 165, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 167, + "ast_sha": "a56059485fea080ecb7a9c4f799d6734b3c9654c3a55e5878fdeb87856ce39b7", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "6fbeac4d1790d89df34976fb6d3e2837296a3f208093021dee993c75e98f6511", + "start_line": 165, + "name": "compressed_extensions", + "arity": 0 + }, + "generate_latest/1:72": { + "line": 72, + "guard": null, + "pattern": "files", + "kind": "defp", + "end_line": 77, + "ast_sha": "85b0ddd42c46c5e419677e98b9a5cf16c0250e670db0953bd5999bdb4dadc163", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "6deeb0070d4f52b0b0d0ce04403f22adf9161ce348d73593f876882a5a4609c1", + "start_line": 72, + "name": "generate_latest", + "arity": 1 + }, + "write_to_disk/2:191": { + "line": 191, + "guard": null, + "pattern": "file, output_path", + "kind": "defp", + "end_line": 227, + "ast_sha": "b6120221786f43d2fe5f094bb3e56c7106ddb2d74dfb80d5266b6b877a1a92af", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "563414a2b87388b5fb58d9b353b957b4e57f8e783c39cbdecd86862b8bddeaca", + "start_line": 191, + "name": "write_to_disk", + "arity": 2 + }, + "digest_stylesheet_asset_references/3:244": { + "line": 244, + "guard": null, + "pattern": "file, latest, with_vsn?", + "kind": "defp", + "end_line": 255, + "ast_sha": "73c9edb6399405dd7ea288fd7fbe7e9cf8bb432f0bd2c5d5a67fbf560bf8e8d3", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "b2afeb812b12e7aa19e34416e237bef7cc54711273630f8946c9c8004ef9254d", + "start_line": 244, + "name": "digest_stylesheet_asset_references", + "arity": 3 + }, + "load_compile_digests/1:82": { + "line": 82, + "guard": null, + "pattern": "output_path", + "kind": "defp", + "end_line": 84, + "ast_sha": "a50b8fb242e4e84e09d7b0d2431e690c1a5b5b7b76741d189b97353d81f211b2", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "a5cf96978375225cfdb3f23dcc27ac26cef594566f9313deaf6e7c8f9c6dea90", + "start_line": 82, + "name": "load_compile_digests", + "arity": 1 + }, + "remove_compressed_file/2:411": { + "line": 411, + "guard": null, + "pattern": "file, output_path", + "kind": "defp", + "end_line": 414, + "ast_sha": "d9fe05681ca2d55e5aa322b6489dd78710dc7e89dcd4ad6f0f0706bd0e50bd11", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "cb0b70354575fea5ed83e50533a4c1189316abdc54df8a6cad703eceaf478bbf", + "start_line": 411, + "name": "remove_compressed_file", + "arity": 2 + }, + "remove_files/2:397": { + "line": 397, + "guard": null, + "pattern": "files, output_path", + "kind": "defp", + "end_line": 403, + "ast_sha": "dc6c32543c6c6f584224fce7efd1e60add65ef5e2bdca9e0ecb135843f26b528", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "9f62f34a5d65aa89e9e53d2698b9c97e4e04f1d8db349acc875d06d2c40fc59d", + "start_line": 397, + "name": "remove_files", + "arity": 2 + }, + "compiled_file?/1:157": { + "line": 157, + "guard": null, + "pattern": "file_path", + "kind": "defp", + "end_line": 162, + "ast_sha": "c8e5f3158b7aa37a9e5dd1da5124616705e41b7639bdea46246bde3a17cd6d87", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "617bc995394019fc73350098af95cbf7edae5599db9bcfe04365c860c1d61662", + "start_line": 157, + "name": "compiled_file?", + "arity": 1 + }, + "manifest_join/2:154": { + "line": 154, + "guard": null, + "pattern": "\".\", filename", + "kind": "defp", + "end_line": 154, + "ast_sha": "cc4fa78313629727486fa0bbcfc9e96603bec93f7fd7686b2a96ffee6968b578", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "a7d9c40238b6e9e3a9eec9b3d12b5b3fd373fa85fce5f8cfa90aea9e8701f821", + "start_line": 154, + "name": "manifest_join", + "arity": 2 + }, + "migrate_manifest/2:101": { + "line": 101, + "guard": null, + "pattern": "_latest, _output_path", + "kind": "defp", + "end_line": 101, + "ast_sha": "2a8f200811f72b988ce9791c19b895cbfad87b6f2e24e4be3f903ab3d6920c87", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "7c9deeade4b650ac3b1fbb9bc46144744ba0e9e684107c670a2ea54b82a931b8", + "start_line": 101, + "name": "migrate_manifest", + "arity": 2 + }, + "migrate_manifest/2:100": { + "line": 100, + "guard": null, + "pattern": "%{\"version\" => 1} = manifest, _output_path", + "kind": "defp", + "end_line": 100, + "ast_sha": "32ff6897153814b2cff38928e2d56fcb01e7bee57df9c140ea4e90e533dcf1e2", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "86909da3bdd96fddddb8ee306b0877da5bd78b51493bae3ec6673480a36a172f", + "start_line": 100, + "name": "migrate_manifest", + "arity": 2 + }, + "save_manifest/4:103": { + "line": 103, + "guard": null, + "pattern": "files, latest, old_digests, output_path", + "kind": "defp", + "end_line": 110, + "ast_sha": "7bcff11f9064a33a2a00c4660606744f24e1c8f264dbc4a69e23c74757182914", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "0bdbcd1359346fa15b948398392ca43a1822f2e6cb58d578db31f5a5485987c7", + "start_line": 103, + "name": "save_manifest", + "arity": 4 + }, + "map_file/2:170": { + "line": 170, + "guard": null, + "pattern": "file_path, input_path", + "kind": "defp", + "end_line": 187, + "ast_sha": "9dd1f4caa5b74c514990da7192656f06634425f560d70f5ea7acb793b9aa5b0e", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "83c1d4e36266335392383739d68342cdb79773fe2f833c3bcf860abe53201839", + "start_line": 170, + "name": "map_file", + "arity": 2 + }, + "relative_digested_path/2:305": { + "line": 305, + "guard": null, + "pattern": "digested_path, true", + "kind": "defp", + "end_line": 306, + "ast_sha": "29360e0cefcb2509a7c702cf9ce181798a80656299c427034837a951e0977cd4", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "18036ac211b5f35cbbf3ae545a911c589955617a135b96c58126f19fd10baafa", + "start_line": 305, + "name": "relative_digested_path", + "arity": 2 + }, + "group_by_logical_path/1:393": { + "line": 393, + "guard": null, + "pattern": "digests", + "kind": "defp", + "end_line": 394, + "ast_sha": "3cbe12b05b2d08b83a25a06e8c2af5cc84a6e08e9f7d020d9e7ac7bc8ab3d448", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "96a7e55813c81deba04ea98c0ca9ad55597e3170aa4e08cf5f24d0a1cf908941", + "start_line": 393, + "name": "group_by_logical_path", + "arity": 1 + }, + "clean_all/1:356": { + "line": 356, + "guard": null, + "pattern": "path", + "kind": "def", + "end_line": 369, + "ast_sha": "30c0e8596ab80a05614c794a291bbd68ac568bfdcce71b0096d68cad6fd86812", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "5a90006c7e9518fd1940ecf76f0dd674c021ad44a171a5b966a0fc7254c4a4c6", + "start_line": 356, + "name": "clean_all", + "arity": 1 + }, + "digest_javascript_asset_references/2:260": { + "line": 260, + "guard": null, + "pattern": "file, latest", + "kind": "defp", + "end_line": 264, + "ast_sha": "0d84c23a0698263417ab993e043a6cd9cee30f70c9f5a2c646c5bff439d9056d", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "1bc20eeb2d61dadf87493cb8b9cde1ec306b7912c41d181a2d9b76b3fd79b3b0", + "start_line": 260, + "name": "digest_javascript_asset_references", + "arity": 2 + }, + "absolute_digested_url/3:314": { + "line": 314, + "guard": null, + "pattern": "url, digested_path, true", + "kind": "defp", + "end_line": 315, + "ast_sha": "66c5451191be2dfc983ab59ce1466bcf38a4f44a53555ae51b8651491911ac0b", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "6721aacf2e562502fe34128a764081009a8f55e0adab97b8af56eab85b5adf87", + "start_line": 314, + "name": "absolute_digested_url", + "arity": 3 + }, + "digested_url/4:276": { + "line": 276, + "guard": null, + "pattern": "<<\"/\"::binary, relative_path::binary>>, _file, latest, with_vsn?", + "kind": "defp", + "end_line": 279, + "ast_sha": "3ffd10dd93e6311867c1003be7182c496c43464561b7f1266ad362a3ff930f8b", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "2e9ec4dc93ab176b30bd0a7d2b1b1798531c71781b4f239bb8138a332b9c2b0c", + "start_line": 276, + "name": "digested_url", + "arity": 4 + }, + "digested_url/4:283": { + "line": 283, + "guard": null, + "pattern": "url, file, latest, with_vsn?", + "kind": "defp", + "end_line": 301, + "ast_sha": "1587fc38f72dfd2df7cedb3984472641cde4d82a36152a3537aa1b47dee43748", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "44eb71259e6f4b4db46c50b88412ebb52267acfeeb1fda5377b5c40981168db1", + "start_line": 283, + "name": "digested_url", + "arity": 4 + }, + "absolute_digested_url/2:320": { + "line": 320, + "guard": null, + "pattern": "url, digested_path", + "kind": "defp", + "end_line": 321, + "ast_sha": "9670b24f5c758d3ec7d2a63661c1e778e61851d4c25840aa463a1889daad2ee8", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "7458554c1211b7ffd401c1ad8b10b2cb5decf16193e159e8fcd4a340cd404943", + "start_line": 320, + "name": "absolute_digested_url", + "arity": 2 + }, + "build_digest/1:144": { + "line": 144, + "guard": null, + "pattern": "file", + "kind": "defp", + "end_line": 150, + "ast_sha": "3b8c20bf0f892c1a1c11797cc659497669e5ea53ccd2ef7ff39feda12c0e3ae1", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "f45bcad07d553d703f031e2d17400d87343774e0b75dbccc34b482b0ef792ea3", + "start_line": 144, + "name": "build_digest", + "arity": 1 + }, + "digest_javascript_map_asset_references/2:268": { + "line": 268, + "guard": null, + "pattern": "file, latest", + "kind": "defp", + "end_line": 272, + "ast_sha": "5a2e09e1757568f50ab7823d9ccc89dfc7e8431b9e39635990e9fcb2269e4303", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "cacb165492550850ea4d3a419af947e5bf8557cc97929fdce992fe44905b7056", + "start_line": 268, + "name": "digest_javascript_map_asset_references", + "arity": 2 + }, + "relative_digested_path/2:308": { + "line": 308, + "guard": null, + "pattern": "digested_path, false", + "kind": "defp", + "end_line": 309, + "ast_sha": "cac99228af0c6c470d5511abc7742587ca67f3ef0f332a60ed286ef80b99e828", + "source_file": "lib/phoenix/digester.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", + "source_sha": "57d0c325f49f5cb51c92a9ec081fd441d4ec524023d33020ae4aca956ee24ba5", + "start_line": 308, + "name": "relative_digested_path", + "arity": 2 + } + }, + "Phoenix.CodeReloader.MixListener": { + "handle_call/3:34": { + "line": 34, + "guard": null, + "pattern": "{:purge, apps}, _from, state", + "kind": "def", + "end_line": 39, + "ast_sha": "172f90fc043460af7436c18b18ce5445ebad09940d3cc6dd1ae71f0069c65b54", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "92dd50d63e8fcbc18322349bdc22afdfd8a475f8da48d0e7fcd4d76b0e3c601c", + "start_line": 34, + "name": "handle_call", + "arity": 3 + }, + "handle_info/2:43": { + "line": 43, + "guard": null, + "pattern": "{:modules_compiled, info}, state", + "kind": "def", + "end_line": 58, + "ast_sha": "c49639fb8b72e7c70528a0cbd1b36744f23f728b8478a4fc2a32a4eb410d4cdb", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "75a6844569f7acc1771172a6ac29a21b17967aa350e370f6e02bdb2f07ca092f", + "start_line": 43, + "name": "handle_info", + "arity": 2 + }, + "handle_info/2:62": { + "line": 62, + "guard": null, + "pattern": "_message, state", + "kind": "def", + "end_line": 63, + "ast_sha": "728932b338eac35c119f0753a66c52537e899c474f33f4919118f8555a9a0a5c", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "c81cec00239d40f9ff67646993cd33a2d4d16dd15476c3fde91fd0afdf7dd7fb", + "start_line": 62, + "name": "handle_info", + "arity": 2 + }, + "init/1:29": { + "line": 29, + "guard": null, + "pattern": "{}", + "kind": "def", + "end_line": 30, + "ast_sha": "657f1484cead00c517722612510816f027304ce03b152b10609ac53350df4c33", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "251a745a3093235b9c1affb8f9a4c0ece8393460283a33b1d4788ebd1bef12b5", + "start_line": 29, + "name": "init", + "arity": 1 + }, + "purge/1:24": { + "line": 24, + "guard": null, + "pattern": "apps", + "kind": "def", + "end_line": 25, + "ast_sha": "8bb81b165868cb611a40506fe388550f6def00a90af49e09d7bf1389f23ef716", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "4c5f7fb829c7b6b65c03dc88ddf55bb1e7d455e42613f76d1337629c9d1e78d8", + "start_line": 24, + "name": "purge", + "arity": 1 + }, + "purge_modules/1:66": { + "line": 66, + "guard": null, + "pattern": "modules", + "kind": "defp", + "end_line": 69, + "ast_sha": "c862cf5ce9d24668d3417a43f413947856878af32e45ab19f62fb04b4bb7fb7d", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "598bd6106b26b6f38e22f835dbd7435e661a0a75e23bf2c7416356a32fc0473b", + "start_line": 66, + "name": "purge_modules", + "arity": 1 + }, + "start_link/1:9": { + "line": 9, + "guard": null, + "pattern": "_opts", + "kind": "def", + "end_line": 10, + "ast_sha": "2e2edfc408d9fa467a6ba05c26264019277120c7d72a528678be9b560661aa1e", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "1abcdfcee769ad69b614e50b5e01da003d46d085ca47734f9c42a136a651302c", + "start_line": 9, + "name": "start_link", + "arity": 1 + }, + "started?/0:14": { + "line": 14, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 15, + "ast_sha": "31f5f95e58dbb61a90025ce5597810d1e7ba7e6f959641ce38d713c962ba3cc8", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "807d9c73b91b44b540e154c5a557c108b8b1bf96207b308fa534d77a491936e6", + "start_line": 14, + "name": "started?", + "arity": 0 + }, + "terminate/2:4": { + "line": 4, + "guard": null, + "pattern": "_reason, _state", + "kind": "def", + "end_line": 4, + "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", + "source_file": "lib/phoenix/code_reloader/mix_listener.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", + "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", + "start_line": 4, + "name": "terminate", + "arity": 2 + } + }, + "Phoenix.VerifiedRoutes": { + "build_conn_forward_path/3:1050": { + "line": 1050, + "guard": null, + "pattern": "%Plug.Conn{} = conn, router, path", + "kind": "defp", + "end_line": 1056, + "ast_sha": "58beb26e867ce72f09c9bfff6cd87f9fd2b1108d6ede73104c3c5a47aecbccda", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "01319430eb83566502e075dfd54453728abc5d20f45a5afd30dc3b85c967d203", + "start_line": 1050, + "name": "build_conn_forward_path", + "arity": 3 + }, + "url/2:539": { + "line": 539, + "guard": null, + "pattern": "conn_or_socket_or_endpoint_or_uri, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", + "kind": "defmacro", + "end_line": 547, + "ast_sha": "682dc7d3b86f658eed2b68c4a980fb1ca6fa7d73803c4e6845fcddbe66ebacf3", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "a2d8587472f584b2b61f2b684ff66913ac0087bacf8be239151556963033940e", + "start_line": 539, + "name": "url", + "arity": 2 + }, + "attr!/2:1021": { + "line": 1021, + "guard": null, + "pattern": "env, :endpoint", + "kind": "defp", + "end_line": 1023, + "ast_sha": "035d8f4e6ee641fe748ca5d8a45b5256bb00461c61daee677ae68af5be0c61f2", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "f0d8200f476e7f8638dac8afc56f099afe2fa3c3ef19fa0ac6cd038d834fca87", + "start_line": 1021, + "name": "attr!", + "arity": 2 + }, + "static_path/2:678": { + "line": 678, + "guard": null, + "pattern": "%Plug.Conn{private: private}, path", + "kind": "def", + "end_line": 681, + "ast_sha": "1db4f06c26c3f4e59a20371461023e9c96a07ef5e427b18934fcaa9150ef578b", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "742190ca97804bef54f14efaa2f475c6070749ff95e51778aae930fa157cb1d9", + "start_line": 678, + "name": "static_path", + "arity": 2 + }, + "verify_segment/3:807": { + "line": 807, + "guard": null, + "pattern": "[_ | _], route, _acc", + "kind": "defp", + "end_line": 809, + "ast_sha": "0ceb4d4d42e8d32454980208c6647d73d24473d28e7d537e0b42702a24eb3e54", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "c58cf7344af8b110bf22711a9f9704121b5de9374919d5e7ff6e27cb9afb0a0d", + "start_line": 807, + "name": "verify_segment", + "arity": 3 + }, + "build_own_forward_path/3:1040": { + "line": 1040, + "guard": null, + "pattern": "conn, router, path", + "kind": "defp", + "end_line": 1045, + "ast_sha": "a3db78d332b93307ab35c0694b3e1a30d6bc8c850f2b03a0440133fb9b9f3708", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "265159a0f4396856028592e669be42a9ea17c4e6fd50cd1b3dd8190b9a738708", + "start_line": 1040, + "name": "build_own_forward_path", + "arity": 3 + }, + "verify_segment/3:768": { + "line": 768, + "guard": null, + "pattern": "[<<\"/\"::binary, _::binary>> = segment | rest], route, acc", + "kind": "defp", + "end_line": 775, + "ast_sha": "5c22453031e75ac7394cbf882d39efb0e47a6b2b2f84d04110aa3154058078e4", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "4dcf049ad408ad9488cb18b064935431aa070334073cda5e6349de37160a6263", + "start_line": 768, + "name": "verify_segment", + "arity": 3 + }, + "path/3:445": { + "line": 445, + "guard": null, + "pattern": "_endpoint, _router, other", + "kind": "defmacro", + "end_line": 445, + "ast_sha": "3f417d2776987fc7e69b505b425bbe132dd3293f82a0de75feb1b0b245d8a556", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "74124352a4be6c4d67e8c6669ec318beb472a8d82786528093ec828d2c763d18", + "start_line": 445, + "name": "path", + "arity": 3 + }, + "static_path?/2:1036": { + "line": 1036, + "guard": null, + "pattern": "path, statics", + "kind": "defp", + "end_line": 1037, + "ast_sha": "51693a41f2e5e98d3c34965aa173d3d1c1d20892dc99a4b603a52d249475d470", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "a3f1e5da5b3bbe06c674a7a1a27b0a4aa5afa79c464f5d8e117486b38fad3d4c", + "start_line": 1036, + "name": "static_path?", + "arity": 2 + }, + "append_params/2:738": { + "line": 738, + "guard": "is_map(params) or is_list(params)", + "pattern": "path, params", + "kind": "defp", + "end_line": 739, + "ast_sha": "ad3924cb8f0e04b7a9ba59b8fcc6221c7825c7f269f8406265b0c01aac10cf02", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "e041040ededbe072e8f50f4e4b5e4c540f382fcccadd4ce1edaf19078a221cf7", + "start_line": 738, + "name": "append_params", + "arity": 2 + }, + "verify_segment/2:758": { + "line": 758, + "guard": null, + "pattern": "[<<\"/\"::binary, _::binary>> | _] = segments, route", + "kind": "defp", + "end_line": 758, + "ast_sha": "d1f90e46d434f14ca57d80947db48bce2e14ac859a33f8d7acc9cd3024f9d9fc", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "22565f0d61ee2024015b3a5f9e9f5383bb23b68eb8377ef6b4d34c743d1e1bdd", + "start_line": 758, + "name": "verify_segment", + "arity": 2 + }, + "unverified_path/4:718": { + "line": 718, + "guard": null, + "pattern": "%URI{} = uri, _router, path, params", + "kind": "def", + "end_line": 719, + "ast_sha": "48bfcf002e72af26682001672f7f4d8c378f605aed740c39219a4d749d266a8f", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "748f926ed0ddfb80d878f6ab28ccf2ad17f3f0fe5cb9526e036e04c4b4fcd920", + "start_line": 718, + "name": "unverified_path", + "arity": 4 + }, + "guarded_unverified_url/3:626": { + "line": 626, + "guard": null, + "pattern": "%Plug.Conn{private: private}, path, params", + "kind": "defp", + "end_line": 629, + "ast_sha": "1b272cf989fe807c59df8c4f86b3061b59526dc68844e2564a2f674459414982", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "78260e3684bc0e29c50e9bf2524b651afe29dee7e7493111998618761be088a9", + "start_line": 626, + "name": "guarded_unverified_url", + "arity": 3 + }, + "expand_alias/2:334": { + "line": 334, + "guard": null, + "pattern": "{:__aliases__, _, _} = alias, env", + "kind": "defp", + "end_line": 335, + "ast_sha": "0adc16b3c706fea8474fd983fb8b9289b8c286ca0f8d13e92c0865cae086158e", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "02dafd1ea2b8b593ef7a47900ce17bf6437216b66645af2703a43fedc98355e9", + "start_line": 334, + "name": "expand_alias", + "arity": 2 + }, + "static_path/2:685": { + "line": 685, + "guard": null, + "pattern": "%URI{} = uri, path", + "kind": "def", + "end_line": 686, + "ast_sha": "7f40926ac8737d60bb4332f3869e4243a39399b1bfdcd79ac4e0c51dbfebee0d", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "caed655409329909626f7ee2ca3bff1a0285224f29864d4f7253d7a4f13721a4", + "start_line": 685, + "name": "static_path", + "arity": 2 + }, + "unverified_url/3:621": { + "line": 621, + "guard": "(is_map(params) or is_list(params)) and is_binary(path)", + "pattern": "conn_or_socket_or_endpoint_or_uri, path, params", + "kind": "def", + "end_line": 623, + "ast_sha": "e93a23e0d0b1151cbeaa7f59a97ab83a07f93177cff0767f92b2fa39c57ef5ca", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "9d001c26ae0732de00f6302880d6cbbcfea01d359d10babf74dd57bc93400af7", + "start_line": 621, + "name": "unverified_url", + "arity": 3 + }, + "guarded_unverified_url/3:637": { + "line": 637, + "guard": null, + "pattern": "%URI{} = uri, path, params", + "kind": "defp", + "end_line": 638, + "ast_sha": "c5c09cfcdf686c0926a69533e9c646f7cf07320644ea577964561874f389c846", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "93acbf727dd1f85d1deeefc5a343e1b629ff1c41caaaa67fb95e47f574edbeac", + "start_line": 637, + "name": "guarded_unverified_url", + "arity": 3 + }, + "url/3:569": { + "line": 569, + "guard": null, + "pattern": "_conn_or_socket_or_endpoint_or_uri, _router, other", + "kind": "defmacro", + "end_line": 569, + "ast_sha": "df6a4d9e6fb9dd48a0f551660216131d425952bf140be917bf0e504e6493d0b4", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "0d553c055f384ecfd849b39ce55975a1e0704be49daf15fa355ad43d323ebfce", + "start_line": 569, + "name": "url", + "arity": 3 + }, + "raise_invalid_route/1:406": { + "line": 406, + "guard": null, + "pattern": "ast", + "kind": "defp", + "end_line": 408, + "ast_sha": "3dc513d21b59bdad6f181d3f50a1fe1acce6c5d0d36704d8a3140f148ca16eb7", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "54af1addda61a2ed37a905b3387812d3811fea58e00832377cbe60adcff6a533", + "start_line": 406, + "name": "raise_invalid_route", + "arity": 1 + }, + "to_param/1:910": { + "line": 910, + "guard": null, + "pattern": "false", + "kind": "defp", + "end_line": 910, + "ast_sha": "cf485e3b01a68a4ae51a615164368a5e004a8ec3c4a8e5bbf57d23b03e221b79", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "1ec4fd8b598c35aa8e676242afd165dfc96f0ff2a49db6531d24c4c55fce334b", + "start_line": 910, + "name": "to_param", + "arity": 1 + }, + "verify_segment/3:785": { + "line": 785, + "guard": null, + "pattern": "[<<\"?\"::binary, static_query_segment::binary>> | rest], route, acc", + "kind": "defp", + "end_line": 786, + "ast_sha": "32eaa57c62b493336f59f3b7972e2b1fcf39a4ee8f60de800a9e469316214088", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "9cd31a18f41f1d58d65cebff842a0f2d946d1a0064c4d3d787b46bcd5c177150", + "start_line": 785, + "name": "verify_segment", + "arity": 3 + }, + "expand_alias/2:337": { + "line": 337, + "guard": null, + "pattern": "other, _env", + "kind": "defp", + "end_line": 337, + "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", + "start_line": 337, + "name": "expand_alias", + "arity": 2 + }, + "unverified_path/4:722": { + "line": 722, + "guard": null, + "pattern": "%_{endpoint: endpoint}, router, path, params", + "kind": "def", + "end_line": 723, + "ast_sha": "b30b1e78381a08a04575a5e99dcdda18023b24df34c1fdd0512b7ddb975ef6a1", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "9112240a69bc48e9cda491b3632fb232bfed65a02bab914f42a731a8151a621d", + "start_line": 722, + "name": "unverified_path", + "arity": 4 + }, + "raise_invalid_query/1:855": { + "line": 855, + "guard": null, + "pattern": "route", + "kind": "defp", + "end_line": 857, + "ast_sha": "ade55884af8ce1760491baa96974fed1168d05ac3dca5f13ea4ec34dc066b46e", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "e10913c3ccf3ee9badf159a83bf7dd2da6de2ade6d2ba79a672a6e01f1856f21", + "start_line": 855, + "name": "raise_invalid_query", + "arity": 1 + }, + "to_param/1:911": { + "line": 911, + "guard": null, + "pattern": "true", + "kind": "defp", + "end_line": 911, + "ast_sha": "e2450a89e6beec2574eb810707567161b09818a7ce3959ade84532d45bbf1501", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "f2e33fb29f90fdb52938d36e082374038c022d31f6604e5e016d2eb4db605936", + "start_line": 911, + "name": "to_param", + "arity": 1 + }, + "__struct__/0:219": { + "line": 219, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 219, + "ast_sha": "263881a97b11577d1b9ea2e0e4bce4f4f0319124db2b0b5d1780ab3f53674b95", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "6b0f19d7ab0dcc97db52ddf76d95137aab2a963a6fa18de787d94f2d28c6ff11", + "start_line": 219, + "name": "__struct__", + "arity": 0 + }, + "to_param/1:912": { + "line": 912, + "guard": null, + "pattern": "data", + "kind": "defp", + "end_line": 912, + "ast_sha": "2188c730bed14579bddf3a4b30bafc421f1b4231c8d7925a3f7b29e7b45f24df", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "f01cd0e9679f9801f15648655ced43ea67cafb7e7f4427127c3c39de76482218", + "start_line": 912, + "name": "to_param", + "arity": 1 + }, + "split_test_path/1:326": { + "line": 326, + "guard": null, + "pattern": "test_path", + "kind": "defp", + "end_line": 331, + "ast_sha": "78cf67d0e790c023d51005b84ff3b306804fa6429d07f68028c13e7735671b25", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "50f0c9e400824d7b573d7687bce35f47a6b056e2e081f2ec696701a924b865b7", + "start_line": 326, + "name": "split_test_path", + "arity": 1 + }, + "append_params/2:736": { + "line": 736, + "guard": "params == %{} or params == []", + "pattern": "path, params", + "kind": "defp", + "end_line": 736, + "ast_sha": "68c29823ef0e7eeb26dbc4ea643e9e1badbb2f50787c803de00ac13e96b15aa0", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "98e19612fefb6f627d58700069d7f5c455b9907fee1e4ff26a29efd11cb87984", + "start_line": 736, + "name": "append_params", + "arity": 2 + }, + "unverified_path/3:708": { + "line": 708, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 708, + "ast_sha": "712cac5b68f49b31a1b5bb0871832d3d760a39167adb009da35dacf02d6472cf", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "ef0848fd17762d4b3da907ff456d28daf7ffbba40f23059b30b94032bb4f8c30", + "start_line": 708, + "name": "unverified_path", + "arity": 3 + }, + "static_integrity/2:882": { + "line": 882, + "guard": null, + "pattern": "%_{endpoint: endpoint}, path", + "kind": "def", + "end_line": 883, + "ast_sha": "342ef67e9088d11ce910bc999eeef83b014c34ad445ae77b4c7e8ac2e704fa28", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "568203a323304ae4c516731437822b35e830fe470c7b1cf26ee92c935c27dd2a", + "start_line": 882, + "name": "static_integrity", + "arity": 2 + }, + "__encode_query__/1:891": { + "line": 891, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 891, + "ast_sha": "da492e005acdddfd4d2d03ff54fa29263da147b69f325b040dcb7ed7e4ebd11d", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "fcfdb988948a62fedfbd3b0386c75556069b7a0f35c83d0811aee00f3a9bc8da", + "start_line": 891, + "name": "__encode_query__", + "arity": 1 + }, + "maybe_sort_query/2:905": { + "line": 905, + "guard": null, + "pattern": "query, true", + "kind": "defp", + "end_line": 906, + "ast_sha": "4ce4e8df43b0bd3b262acabbe53a157c6b0566f68ae216215f1dc4a77f1c02e9", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "9ce2611bd19e853d89247f3790e45130d1889c2d5efdcd45dd03ab5e0ea2213f", + "start_line": 905, + "name": "maybe_sort_query", + "arity": 2 + }, + "__encode_query__/2:893": { + "line": 893, + "guard": "is_list(dict) or\n (is_map(dict) and\n not (is_map(dict) and is_map_key(:__struct__, dict) and is_atom(map_get(:__struct__, dict))))", + "pattern": "dict, sort?", + "kind": "def", + "end_line": 897, + "ast_sha": "79d135599d6e235a0b417bbbbd423e62bc4114de1269cd78de1f256d992b0742", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b61eb40dc569c77344ab0cbb2d01d2d87eaacdca5c6d1a5eeb2f324860e17854", + "start_line": 893, + "name": "__encode_query__", + "arity": 2 + }, + "static_path/2:689": { + "line": 689, + "guard": null, + "pattern": "%_{endpoint: endpoint}, path", + "kind": "def", + "end_line": 690, + "ast_sha": "f41bbba47ba162c9a3e4b4e819534d8db2975aba2101af444e2fb2b7732433a1", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "15c21fd3f9e91b26df0221bc8c910feaacf1e4e8045fef76d7caedfc06b4b0ac", + "start_line": 689, + "name": "static_path", + "arity": 2 + }, + "__using__/2:246": { + "line": 246, + "guard": null, + "pattern": "mod, opts", + "kind": "def", + "end_line": 270, + "ast_sha": "0b402e615c188842756a71b68bde80619ab38d80cf04c46dff2ed8146ee4323f", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "cfe1bc7fd5cb52c52b18f74f79d9cba61e259f0c6eea98a199affe1ff9bf7067", + "start_line": 246, + "name": "__using__", + "arity": 2 + }, + "verify_query/3:838": { + "line": 838, + "guard": null, + "pattern": "[\"=\" | rest], route, acc", + "kind": "defp", + "end_line": 839, + "ast_sha": "92498feb7834d40d0ceab794ebc385dc3076164e8b677bbbc75f349ebb4a8584", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "909705504460a3b23cdb95051c5769840f36f61e08aee5b851a2e50a93293008", + "start_line": 838, + "name": "verify_query", + "arity": 3 + }, + "__encode_query__/2:901": { + "line": 901, + "guard": null, + "pattern": "val, _sort?", + "kind": "def", + "end_line": 901, + "ast_sha": "31c8ebe0ef090a9b24ce095c5f184ec79b986fcabced5fc7b1aa8bd0b7e18fbf", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "c4a1ded39450d5724d98ff157422e8c7215881492530cc5a19acd948218b44dc", + "start_line": 901, + "name": "__encode_query__", + "arity": 2 + }, + "__verify__/1:313": { + "line": 313, + "guard": "is_list(routes)", + "pattern": "routes", + "kind": "def", + "end_line": 320, + "ast_sha": "26ba035746aee2c1d150bc150c3e8b266d1e78aaaed9c1f62185e7f0cf7f58be", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "6015421613c6ae00ee75da5eaa73916aabb9e6ba31399d2131f4cd1ed5e54025", + "start_line": 313, + "name": "__verify__", + "arity": 1 + }, + "encode_segment/1:751": { + "line": 751, + "guard": null, + "pattern": "data", + "kind": "defp", + "end_line": 754, + "ast_sha": "40330b5cadad8aaeb5f14cb7da8298845aa0aa5f167a45c5129deff61d51e085", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "6b9a3f1b4c453010e2886278248b6432b5160f0403eeae961c7d84d83d9b74d3", + "start_line": 751, + "name": "encode_segment", + "arity": 1 + }, + "verify_query/3:836": { + "line": 836, + "guard": null, + "pattern": "[], _route, acc", + "kind": "defp", + "end_line": 836, + "ast_sha": "7f8c0ed28af8fef1541b7861a0e2e369955f46b26ef01efe354e7965fcb81083", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "ecafca31ca5f9c0d99ed258c5a85c3e0873f93666f2e37508405210dd085c705", + "start_line": 836, + "name": "verify_query", + "arity": 3 + }, + "__using__/1:225": { + "line": 225, + "guard": null, + "pattern": "opts", + "kind": "defmacro", + "end_line": 241, + "ast_sha": "5815d3b815808c22db1824310487f21c7661a2ceb70676e9e8e60dbfee28e646", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "c67d1ba990d01bbc587755da98fa80d26c12780abbb8ce13ecc8ba17d3a1a6d7", + "start_line": 225, + "name": "__using__", + "arity": 1 + }, + "path/2:480": { + "line": 480, + "guard": null, + "pattern": "_conn_or_socket_or_endpoint_or_uri, other", + "kind": "defmacro", + "end_line": 480, + "ast_sha": "2787a5f5b23602cc50be7dd6eb718a21b5f44b7dfe7a5057d5eeb13930f5fdfd", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b470291bbcf412e4404b60cf3068581f152814e8e3508c32aec448afbf77ce6f", + "start_line": 480, + "name": "path", + "arity": 2 + }, + "unverified_path/4:710": { + "line": 710, + "guard": null, + "pattern": "%Plug.Conn{} = conn, router, path, params", + "kind": "def", + "end_line": 715, + "ast_sha": "7c0d10153dea2b6ef04181eb225821398f6c732fb8280707e354fdbaf60eb43f", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "337fa9d163f808fadbc58f61e3a3dec17b0d1bad3f496a083b84a90aab84d6eb", + "start_line": 710, + "name": "unverified_path", + "arity": 4 + }, + "verify_query/3:851": { + "line": 851, + "guard": null, + "pattern": "_other, route, _acc", + "kind": "defp", + "end_line": 852, + "ast_sha": "ff7fba30e0ca646179d20023acdc9ed59f7e656fa766fa0a0866a2a6cd6927f7", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "257e48e9edce2bc85730718392f4070f1a607644b4496a07315da3fd7d2d0a0e", + "start_line": 851, + "name": "verify_query", + "arity": 3 + }, + "url/2:550": { + "line": 550, + "guard": null, + "pattern": "_conn_or_socket_or_endpoint_or_uri, other", + "kind": "defmacro", + "end_line": 550, + "ast_sha": "2787a5f5b23602cc50be7dd6eb718a21b5f44b7dfe7a5057d5eeb13930f5fdfd", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "a7f5a1dbd4260f8a476a8f30bc483682a19b368177a74f8baecfc293012c7ca0", + "start_line": 550, + "name": "url", + "arity": 2 + }, + "warn_location/2:944": { + "line": 944, + "guard": null, + "pattern": "meta, %{line: line, file: file, function: function, module: module}", + "kind": "defp", + "end_line": 946, + "ast_sha": "8de72d9738543a9f1cfd97ba90490eea8b3dbb55887cdc2113b38be057a358f9", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "14b82d1cd0aa82aedf0e05f68e94420b032401a4a4446116ee73a2fef915e7b9", + "start_line": 944, + "name": "warn_location", + "arity": 2 + }, + "verify_segment/3:813": { + "line": 813, + "guard": null, + "pattern": "[], _route, acc", + "kind": "defp", + "end_line": 813, + "ast_sha": "699bcbccab5d404858deba881ac9d76ff04bd4dc208dec6ca22aacac392a7e20", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "05981265f54bebebf0030f1519c48a3dd8b316e5f223d83ee855f9019998b2dd", + "start_line": 813, + "name": "verify_segment", + "arity": 3 + }, + "to_param/1:908": { + "line": 908, + "guard": "is_integer(int)", + "pattern": "int", + "kind": "defp", + "end_line": 908, + "ast_sha": "fc0a53d67074be1b3315b576026e16d19187f2a672d53756e7f0754bcd8d184a", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b176908d74f08eed0e4d5c951396e376af92fe6cb74bfdca191f425d041bcb7b", + "start_line": 908, + "name": "to_param", + "arity": 1 + }, + "build_route/5:914": { + "line": 914, + "guard": null, + "pattern": "route_ast, sigil_p, env, endpoint_ctx, router", + "kind": "defp", + "end_line": 940, + "ast_sha": "620ac3e06c453ef36b9107eb1f1f7968a79d9539bbbfa6acf4882f4471585407", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b0e26a087808fac4814bfa4de29cbea17b8b6ca95f16ad1b2f03efe2f7513baf", + "start_line": 914, + "name": "build_route", + "arity": 5 + }, + "url/3:557": { + "line": 557, + "guard": null, + "pattern": "conn_or_socket_or_endpoint_or_uri, router, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", + "kind": "defmacro", + "end_line": 566, + "ast_sha": "37b5bf0561732cbc5ba34ea9b56590d79e9a26c5728935d66d044d27fcfdb989", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "8aad4351397db351962fc56dd9538294cbf13bf10779b48a3cd547638a077c3c", + "start_line": 557, + "name": "url", + "arity": 3 + }, + "guarded_unverified_url/3:633": { + "line": 633, + "guard": null, + "pattern": "%_{endpoint: endpoint}, path, params", + "kind": "defp", + "end_line": 634, + "ast_sha": "9f2cde53921934913e384e759aad102ca6f1de9bf1a8b83cd1542434d204c1d1", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "5ef91c60b7c483a9fbbbee05a92f80f90821bc39d08ea22364385deb424977eb", + "start_line": 633, + "name": "guarded_unverified_url", + "arity": 3 + }, + "path_with_script/2:1060": { + "line": 1060, + "guard": null, + "pattern": "path, []", + "kind": "defp", + "end_line": 1060, + "ast_sha": "c2dec8193e4fbe1790877b6f68eda4a42f219538978a80a77fc85da4bfd38940", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "fdb5fc337dae0751b2159bfc44fe8c4298db473a4e4e297a4993fd92e7f9e29e", + "start_line": 1060, + "name": "path_with_script", + "arity": 2 + }, + "concat_url/3:653": { + "line": 653, + "guard": "is_binary(path)", + "pattern": "url, path, params", + "kind": "defp", + "end_line": 654, + "ast_sha": "0f89dfb154974925dce78b46ce21e27d5df4b242c8f8478c6fb9620f3b72509b", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "2b0362934fb74043fcfbb4352f562ebdbab4924866559568d4cc33e442865833", + "start_line": 653, + "name": "concat_url", + "arity": 3 + }, + "guarded_unverified_url/3:645": { + "line": 645, + "guard": null, + "pattern": "other, path, _params", + "kind": "defp", + "end_line": 648, + "ast_sha": "8c21c464b01ca9915352473db9ad573fd2c7fcadf09fd679c261c4b379501dff", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "f55c67c4534be03d459c9e71be60a1f29a19d61b468aca42c17e80bdb0a61592", + "start_line": 645, + "name": "guarded_unverified_url", + "arity": 3 + }, + "static_path/2:693": { + "line": 693, + "guard": "is_atom(endpoint)", + "pattern": "endpoint, path", + "kind": "def", + "end_line": 694, + "ast_sha": "6755c53859bb0b7e85a5a3068213de93b94543ab79300a0899777fd47c4e87d2", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "eb5873caabf800000baaf1684b530c980d342a740ec661ebc5ddc6d79b3581db", + "start_line": 693, + "name": "static_path", + "arity": 2 + }, + "static_url/2:604": { + "line": 604, + "guard": null, + "pattern": "other, path", + "kind": "def", + "end_line": 607, + "ast_sha": "2e82ddfa49392608c1ceeecde04b414c4305f0b2dfffaf45c89aaa85ea5dde6f", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "43db59e9f158bc7f1899dffc706d9f8dd9ca0f0cb04ef72ddd8d9489a4ec7485", + "start_line": 604, + "name": "static_url", + "arity": 2 + }, + "sigil_p/2:361": { + "line": 361, + "guard": null, + "pattern": "{:<<>>, _meta, _segments} = route, extra", + "kind": "defmacro", + "end_line": 368, + "ast_sha": "54821b040a1f4976ec40b2757c0f88d07e76bafd447bbd2a178b061e0c58e9b5", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "3be08178e952876e8aec4a988ffc4d6d063750c197aa04fc245e518a453302e8", + "start_line": 361, + "name": "sigil_p", + "arity": 2 + }, + "to_param/1:909": { + "line": 909, + "guard": "is_binary(bin)", + "pattern": "bin", + "kind": "defp", + "end_line": 909, + "ast_sha": "a6ef8ff1e6d49bbb2526e189ac63dfe3c7959a3a00479d2d6645f5c7018916c5", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "77c8da775fa03fa721aae5347531df7608e5e7edc4bd9a2510d84c664fa90340", + "start_line": 909, + "name": "to_param", + "arity": 1 + }, + "validate_sigil_p!/1:400": { + "line": 400, + "guard": null, + "pattern": "[]", + "kind": "defp", + "end_line": 400, + "ast_sha": "50efa1e95ba3092268d96d48c2d0407a130e60f7bda6918fa3cb64eadf7833a0", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "1aaf7ce59b3bcebaa4da918b80ee71d0540768fb48b44e1b86bddafa5710ac7c", + "start_line": 400, + "name": "validate_sigil_p!", + "arity": 1 + }, + "compile_prefixes/2:1002": { + "line": 1002, + "guard": null, + "pattern": "path_prefixes, meta", + "kind": "defp", + "end_line": 1013, + "ast_sha": "4e1f062722956c99fef4fc518705d9436111de59133818280cda02e40b6ee3f7", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "7235146e16b78d2d8f1c1049ef64974f72b7ca2564ca59bd71a80c9f193b8c26", + "start_line": 1002, + "name": "compile_prefixes", + "arity": 2 + }, + "validate_sigil_p!/1:402": { + "line": 402, + "guard": null, + "pattern": "extra", + "kind": "defp", + "end_line": 403, + "ast_sha": "c3cee8f41843a92ce260d58539e1c72d2a20134d2dff5d4ed2f95f155d9eaa38", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "0cc81a96f40ad67f644873c1a47f004c42fb884a02de9b36238def3528505d74", + "start_line": 402, + "name": "validate_sigil_p!", + "arity": 1 + }, + "static_integrity/2:878": { + "line": 878, + "guard": null, + "pattern": "%Plug.Conn{private: %{phoenix_endpoint: endpoint}}, path", + "kind": "def", + "end_line": 879, + "ast_sha": "e5692521ab8bee838e8df7bf343df27cd1b6a0c5d3869d76472bb231de993f01", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "59aeba43c5a34bfa32e2f6de5075eee8a09b66d7c7febaa769b83d6d0bb67a6d", + "start_line": 878, + "name": "static_integrity", + "arity": 2 + }, + "attr!/2:1017": { + "line": 1017, + "guard": null, + "pattern": "%{function: nil}, _", + "kind": "defp", + "end_line": 1018, + "ast_sha": "42b47ae6dba0f45dc8ad98c2f4cb24649e78780d72c803124b68562c1302738a", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "24f1e7007f7ab2e736b249a94221fbbc1c781dc9d3fc36624229d5f3732e77dc", + "start_line": 1017, + "name": "attr!", + "arity": 2 + }, + "concat_url/2:651": { + "line": 651, + "guard": "is_binary(path)", + "pattern": "url, path", + "kind": "defp", + "end_line": 651, + "ast_sha": "358424e5720b2b89cb29fde27b9a6a1f8f5538f0d5885e85cd33be9d94a55586", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "26f58ad54c544c9c41d1e2f7eecaae7ea069c3002be89705355be4f683661c47", + "start_line": 651, + "name": "concat_url", + "arity": 2 + }, + "url/1:532": { + "line": 532, + "guard": null, + "pattern": "other", + "kind": "defmacro", + "end_line": 532, + "ast_sha": "85b5fc7397263ab4f9ed06122a10ffcea71e2ff7c620b36e2414f91d4c6975c9", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "1de80c3ea3a965c3b010ebecc7b270c362a41a1724221c52d510ab4f45d5a9f9", + "start_line": 532, + "name": "url", + "arity": 1 + }, + "static_url/2:596": { + "line": 596, + "guard": null, + "pattern": "%_{endpoint: endpoint}, path", + "kind": "def", + "end_line": 597, + "ast_sha": "170dab7ca873814e1bd6f1f24dca78b45f06833151aa7edae6afd25dc18b0901", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "1fa5edb2875c387c498bd5b5f9cfb8dcafaf049283fac21a06ac5f2d99a7a6f8", + "start_line": 596, + "name": "static_url", + "arity": 2 + }, + "url/1:523": { + "line": 523, + "guard": null, + "pattern": "{:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", + "kind": "defmacro", + "end_line": 529, + "ast_sha": "f482053b161f9ea2a4a057a759b70649da7d4c4e65b21da3f99b701d786e2d0f", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "9cf85178b06b10a334405c2f29c5352166df291bbc78f198cbbe00ae38a9da75", + "start_line": 523, + "name": "url", + "arity": 1 + }, + "verify_segment/3:780": { + "line": 780, + "guard": null, + "pattern": "[<<\"?\"::binary, query::binary>>], _route, acc", + "kind": "defp", + "end_line": 781, + "ast_sha": "f42a238a85d90da5619bd9d0f87bd62e9295da91b2e5e0a5f0f65ff57afed604", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "2e194705b1bad49c4a98121fb857617acd2dac47d29679d9b7547560b98fafb2", + "start_line": 780, + "name": "verify_segment", + "arity": 3 + }, + "materialize_path/1:998": { + "line": 998, + "guard": null, + "pattern": "path", + "kind": "defp", + "end_line": 999, + "ast_sha": "96349d5e9917ebaf47ac31aac793c3391635313ce84f11c48d7287b9314fe65c", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "44fe0d44e89040c5abdecf6e493db1aaf4ff63be789daff925316cc49d894821", + "start_line": 998, + "name": "materialize_path", + "arity": 1 + }, + "static_url/2:600": { + "line": 600, + "guard": "is_atom(endpoint)", + "pattern": "endpoint, path", + "kind": "def", + "end_line": 601, + "ast_sha": "9a4dd50032f46e77c98d6a26ecb804250e4c243520238dca498480ae59462739", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "eece47a5cf6f8208a412d062f08a65bbcf1fb916f9012a97a8ccc0a34f3ca253", + "start_line": 600, + "name": "static_url", + "arity": 2 + }, + "inject_path/2:371": { + "line": 371, + "guard": null, + "pattern": "{%Phoenix.VerifiedRoutes{} = route, static?, _endpoint_ctx, _route_ast, path_ast, static_ast}, env", + "kind": "defp", + "end_line": 379, + "ast_sha": "1c28b8d1d00140bf1ed56b89613e1bf407081090d843e4a87f9706aa4ccffd43", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "fcc0f153737815c6915a1b15973a8214bb1d2328df9a923a46eedc346507d995", + "start_line": 371, + "name": "inject_path", + "arity": 2 + }, + "attr!/2:1032": { + "line": 1032, + "guard": null, + "pattern": "env, name", + "kind": "defp", + "end_line": 1033, + "ast_sha": "57f3d330e0e6eee41b33bf7bb346bb778a8fc918293a772ecf4ef352e7b3ac97", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "7dd4f8ddbbb74ad0744f28ff3bc5747789fa2f5d7209d473836143608580a6c3", + "start_line": 1032, + "name": "attr!", + "arity": 2 + }, + "__struct__/1:219": { + "line": 219, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 219, + "ast_sha": "475883802c714d67250991abdd9ab7892bedf7bd511444c9a5471740c5192ac2", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "6b0f19d7ab0dcc97db52ddf76d95137aab2a963a6fa18de787d94f2d28c6ff11", + "start_line": 219, + "name": "__struct__", + "arity": 1 + }, + "unverified_path/4:730": { + "line": 730, + "guard": null, + "pattern": "other, router, path, _params", + "kind": "def", + "end_line": 733, + "ast_sha": "aa6af246adf3d96da2c03c779f8bbdcc599ba00262fc59cdd6b0dc2725ad8ecb", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "62d6b5bb0f124227f30133ddfc20a095e25e1d0f043822319f93c856ee130f88", + "start_line": 730, + "name": "unverified_path", + "arity": 4 + }, + "static_integrity/2:886": { + "line": 886, + "guard": "is_atom(endpoint)", + "pattern": "endpoint, path", + "kind": "def", + "end_line": 887, + "ast_sha": "42bf544c0863fea9770afbeee941d9c565615570b11050c0a10096af5163f306", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "d1f27405e27577254ae84a5422cbcac885dbfa2ac0bc36eed91e3d18fd784a0b", + "start_line": 886, + "name": "static_integrity", + "arity": 2 + }, + "path_with_script/2:1061": { + "line": 1061, + "guard": null, + "pattern": "path, script", + "kind": "defp", + "end_line": 1061, + "ast_sha": "cc6b3b797aa992bd6b3e60f103b8c1fd51fc2f435ddbe1dfb5afb597514fd5e7", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "85e62c3e2c775a67b4c117061e12ad387a56dd06322b0d1552c685a80309b8fe", + "start_line": 1061, + "name": "path_with_script", + "arity": 2 + }, + "verify_segment/3:794": { + "line": 794, + "guard": "is_binary(prev)", + "pattern": "[{:\"::\", m1, [{{:., m2, [Kernel, :to_string]}, m3, [dynamic]}, {:binary, _, _} = bin]} | rest], route, [prev | _] = acc", + "kind": "defp", + "end_line": 804, + "ast_sha": "c80dd0cccfd7e8fd3ff79ed0883fcee8ba5673ae3a52db31aae85f9ee25f4538", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "ad7ffdf7585e09935ccc3826a5edcd725f5e0978f056ba529bd1d9fc3ae1e4e6", + "start_line": 794, + "name": "verify_segment", + "arity": 3 + }, + "__before_compile__/1:299": { + "line": 299, + "guard": null, + "pattern": "_env", + "kind": "defmacro", + "end_line": 306, + "ast_sha": "65bad7c7df5707b52710cf59097e8288493b316972d6004ff7d784f6168ef6e6", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "178fcbcc40532fc100ce74c612b763fcff2a4a5ffc3f13e617c1627900a1ccd6", + "start_line": 299, + "name": "__before_compile__", + "arity": 1 + }, + "verify_segment/3:789": { + "line": 789, + "guard": "is_binary(segment)", + "pattern": "[segment | _], route, _acc", + "kind": "defp", + "end_line": 791, + "ast_sha": "8ebd595004bfa720a2741926f9e911d70f9f43d86b01ecd6c6f4711b6ec6dd69", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "da3d3ace4d18776a09b5756c7433c6d4df89a0b0307e71e4147a0f175e2ac919", + "start_line": 789, + "name": "verify_segment", + "arity": 3 + }, + "unverified_path/4:726": { + "line": 726, + "guard": "is_atom(endpoint)", + "pattern": "endpoint, _router, path, params", + "kind": "def", + "end_line": 727, + "ast_sha": "aef6a17673bedc5dd56d2c433be91f7cf7c9f8bcfcd894f2653a57183154de6d", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "21c8e977219f17627ecf1d755dd970307779626a2eced3bc65a4d8943fea00e5", + "start_line": 726, + "name": "unverified_path", + "arity": 4 + }, + "path/3:433": { + "line": 433, + "guard": null, + "pattern": "conn_or_socket_or_endpoint_or_uri, router, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, extra]} = sigil_p", + "kind": "defmacro", + "end_line": 442, + "ast_sha": "72e3f98cc7f90d4e11973747c8234b0f3c385ef102b16197d65fb1dbb480711e", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "ab60b4f429317e7dfcb9ee3e396cd980f8d4321433df3e1a949b3d6ae6fd788d", + "start_line": 433, + "name": "path", + "arity": 3 + }, + "verify_segment/2:760": { + "line": 760, + "guard": null, + "pattern": "_, route", + "kind": "defp", + "end_line": 761, + "ast_sha": "7c8adea71836ce2672b6146a35c0c36e8032840da0a490b4c8d583a66094a6b1", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "85d418198cab54ea84f7a71882f3d959be33483ffb52e8c6b42b35ec49574862", + "start_line": 760, + "name": "verify_segment", + "arity": 2 + }, + "verify_segment/3:765": { + "line": 765, + "guard": null, + "pattern": "[\"/\" | rest], route, acc", + "kind": "defp", + "end_line": 765, + "ast_sha": "f426fae66ac0b58fe291aed0adb8f9db9de8add952de2325bca3544a269a503e", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "adbcdd5d9d67392e6c4dd870c2d1fd49937b9d787288ae5dcdde8d0b2b5aeba5", + "start_line": 765, + "name": "verify_segment", + "arity": 3 + }, + "maybe_sort_query/2:903": { + "line": 903, + "guard": null, + "pattern": "query_str, false", + "kind": "defp", + "end_line": 903, + "ast_sha": "fcecd77d337df8c8adf991ddba46ca7f23940578518531d374145a1afac9017c", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "6b5de0fb0ee730ab97c6166473381b8301d1dd66800bfa9458471359a388dfb9", + "start_line": 903, + "name": "maybe_sort_query", + "arity": 2 + }, + "guarded_unverified_url/3:641": { + "line": 641, + "guard": "is_atom(endpoint)", + "pattern": "endpoint, path, params", + "kind": "defp", + "end_line": 642, + "ast_sha": "fd7637e250dde05517dca969081264c02cb108140f1b60548df2a8883127d053", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "b49b9c7ae8a37fae09e991764ad7d739b002b26faa0c9f7d8fa78163930ff6cd", + "start_line": 641, + "name": "guarded_unverified_url", + "arity": 3 + }, + "__encode_segment__/1:743": { + "line": 743, + "guard": null, + "pattern": "data", + "kind": "def", + "end_line": 747, + "ast_sha": "db5b8ee10fd51341688a487326a921e4b8047ca157839ffe8bf6c5b8b1b4800d", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "8b8e6f2d93068e0b1a590eb65d38d76dfcf1ec45de8471b93ba7354b3781c3ab", + "start_line": 743, + "name": "__encode_segment__", + "arity": 1 + }, + "static_url/2:589": { + "line": 589, + "guard": null, + "pattern": "%Plug.Conn{private: private}, path", + "kind": "def", + "end_line": 592, + "ast_sha": "f20a10d6e6525f095a5a1a94084242f14f923c5962cde7240285b5cbb82c6875", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "85f56b40953ab0dbebaa53a38c87cd261f26268d46f84d32d8f7d5fb5461247f", + "start_line": 589, + "name": "static_url", + "arity": 2 + }, + "verify_query/3:815": { + "line": 815, + "guard": null, + "pattern": "[{:\"::\", m1, [{{:., m2, [Kernel, :to_string]}, m3, [arg]}, {:binary, _, _} = bin]} | rest], route, acc", + "kind": "defp", + "end_line": 833, + "ast_sha": "3d6135b15ff0aae3b1d0e7e44927a3af905e4c77cac8f7234184651c0d779c20", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "11cf0c65227e79040317fba8671af53891ef234b7d288549f37431c7ba4eb559", + "start_line": 815, + "name": "verify_query", + "arity": 3 + }, + "rewrite_path/4:954": { + "line": 954, + "guard": null, + "pattern": "route, endpoint, router, config", + "kind": "defp", + "end_line": 995, + "ast_sha": "559eddce3975aebf63a89a4fa2245fc67afe13f7f18ec02c5dcec18c9a80b92e", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "95441a0ed6304499e33cfdd40746ee15d12fc88a25e4152a4b27a3500ca28196", + "start_line": 954, + "name": "rewrite_path", + "arity": 4 + }, + "path/2:468": { + "line": 468, + "guard": null, + "pattern": "conn_or_socket_or_endpoint_or_uri, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, extra]} = sigil_p", + "kind": "defmacro", + "end_line": 477, + "ast_sha": "234bcc347783d64ed03e1b1fe83eb76216e28734ffe3aaf993f7556eed7a5bdd", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "161e7c195bda8a4a1d7f6cd2a86b6979d052bd7e360cf7d2de661b949469fc84", + "start_line": 468, + "name": "path", + "arity": 2 + }, + "unverified_url/2:621": { + "line": 621, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 621, + "ast_sha": "b368d69c7d9c4c4cbd069353ce290b29be6e77dc864ea2ba15ead8a3483039aa", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "34261e720a2cf97517cca674f9b04bf5df94271dd1f728be4685ca70c9539122", + "start_line": 621, + "name": "unverified_url", + "arity": 2 + }, + "verify_query/3:842": { + "line": 842, + "guard": null, + "pattern": "[<<\"&\"::binary, _::binary>> = param | rest], route, acc", + "kind": "defp", + "end_line": 848, + "ast_sha": "f2dc71f5606ce2473f59713e2e7769b05ac6a76b1c2bf8547aec564ba5906642", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "bda827a3f45e71017c3732e8dd3842f24fd9b26618d6d7732ff6cce384c8ba22", + "start_line": 842, + "name": "verify_query", + "arity": 3 + }, + "inject_url/2:383": { + "line": 383, + "guard": null, + "pattern": "{%Phoenix.VerifiedRoutes{} = route, static?, endpoint_ctx, route_ast, path_ast, _static_ast}, env", + "kind": "defp", + "end_line": 395, + "ast_sha": "be2ee12036bf0180fa0e05946f89afc0d4108756c4c239869b96328b5391b761", + "source_file": "lib/phoenix/verified_routes.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", + "source_sha": "c6165001c597bae9d10f022c4ee7f6e175e3b0ab9c6f578d22ffc462a9bbcbbd", + "start_line": 383, + "name": "inject_url", + "arity": 2 + } + }, + "Mix.Tasks.Phx.Gen.Json": { + "context_files/1:181": { + "line": 181, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: true} = context", + "kind": "defp", + "end_line": 182, + "ast_sha": "08e5af0af95b4ae237e06db824c74ba9d18fab30ffa137939e2db412b4640e6c", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", + "start_line": 181, + "name": "context_files", + "arity": 1 + }, + "context_files/1:185": { + "line": 185, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: false}", + "kind": "defp", + "end_line": 185, + "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", + "start_line": 185, + "name": "context_files", + "arity": 1 + }, + "copy_new_files/3:208": { + "line": 208, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", + "kind": "def", + "end_line": 213, + "ast_sha": "e80492f8d42f38a04d4142af4fd674a377fcf2d4bc7c910c9a239fb0d5a4a953", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "09fbc38690a3a422ade53a0dbdfcea0a4da3d9f3eb29a4bff943686861859365", + "start_line": 208, + "name": "copy_new_files", + "arity": 3 + }, + "files_to_be_generated/1:190": { + "line": 190, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", + "kind": "def", + "end_line": 203, + "ast_sha": "99755c2901c4ba78adb48b171586277917e034b4613812e477b9e06ba60d65ef", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "5bb596b6d830071d81ca417e3419538cc6efa7b2e52a90f56b9a85ebe670dd19", + "start_line": 190, + "name": "files_to_be_generated", + "arity": 1 + }, + "print_shell_instructions/1:217": { + "line": 217, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", + "kind": "def", + "end_line": 251, + "ast_sha": "2afeb9c71c24bb4c58beb193f785513b7cb0ad48379bee9b7f81c33da08a3617", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "1856a021e2ae5179db396198ece6b5c2daaa17e5adff585a2972347c6c5e81b0", + "start_line": 217, + "name": "print_shell_instructions", + "arity": 1 + }, + "run/1:122": { + "line": 122, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 171, + "ast_sha": "70c972e1a84c1e1c3e289731a0d80eccb9902cc87b7e823c204e4655a5ebc5b5", + "source_file": "lib/mix/tasks/phx.gen.json.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", + "source_sha": "d471fe82a890711861ec3544b637e51dcadb04ae7e7c0fd5d471fb30c5a42865", + "start_line": 122, + "name": "run", + "arity": 1 + } + }, + "Phoenix.Param.BitString": { + "__impl__/1:74": { + "line": 74, + "guard": null, + "pattern": ":protocol", + "kind": "def", + "end_line": 74, + "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "e5189dff34782443626d21e7baf075a52e34162ae2dec628696fd0eb21618632", + "start_line": 74, + "name": "__impl__", + "arity": 1 + }, + "to_param/1:75": { + "line": 75, + "guard": "is_binary(bin)", + "pattern": "bin", + "kind": "def", + "end_line": 75, + "ast_sha": "bd32b5e49ccf4d79a4bc0cc43fcee6b8f1c96d5c18bc46c445e758b2d40541d2", + "source_file": "lib/phoenix/param.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", + "source_sha": "a545c9e051e728852d4e4cae25feab27eb39d5ab68185341436b42afe782280d", + "start_line": 75, + "name": "to_param", + "arity": 1 + } + }, + "Mix.Phoenix": { + "app_base/1:159": { + "line": 159, + "guard": null, + "pattern": "app", + "kind": "defp", + "end_line": 162, + "ast_sha": "f1db8d37a952cd17d68f258a5ecdfceecad9b239102aea768d4e8bc857cbb70b", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "63e64de731791509c63385ef7496b3d67a0857199751b3a959ca8dfe7fca91fd", + "start_line": 159, + "name": "app_base", + "arity": 1 + }, + "base/0:144": { + "line": 144, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 145, + "ast_sha": "3b256704e6abf10d712eaff8da852b74203465c695d856066eee0f6cc7572f7a", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "60f56f74eaa67c5e3ab03fc669836650a2bfc101cdbcbc24340962a070ca8f5a", + "start_line": 144, + "name": "base", + "arity": 0 + }, + "beam_to_module/1:183": { + "line": 183, + "guard": null, + "pattern": "path", + "kind": "defp", + "end_line": 184, + "ast_sha": "a7c6968c70bdc5dc6047664097cb8bd06c13247de89b6c076d6abc218f3a639b", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "8e86b1b3d98423c9e718fe79cea69b1cc10775ef1444825883dc630f718595f2", + "start_line": 183, + "name": "beam_to_module", + "arity": 1 + }, + "check_module_name_availability!/1:129": { + "line": 129, + "guard": null, + "pattern": "name", + "kind": "def", + "end_line": 133, + "ast_sha": "74a11de9b758f58971fd7695cd31de6af7f196cbf69087447ccfe818e58b0300", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "22ceb8a40cd33cd694a4eb19464dd8c7f309b3b9caf682d9135cf63549b1c55b", + "start_line": 129, + "name": "check_module_name_availability!", + "arity": 1 + }, + "context_app/0:256": { + "line": 256, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 261, + "ast_sha": "fdeffeeb5ca112741b9468e9a45404b9070b1f88a2c4c3582e5303ec588f3fc1", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "b4a83922b23b0f0877ad86f39e3ffc1da1be27752ebb7c77d5c19d706742cb2f", + "start_line": 256, + "name": "context_app", + "arity": 0 + }, + "context_app_path/2:223": { + "line": 223, + "guard": "is_atom(ctx_app)", + "pattern": "ctx_app, rel_path", + "kind": "def", + "end_line": 235, + "ast_sha": "cb97f7b27fe2a6ce0116c175b5edd3129d8c3b7df0cbadcfbe5152bd4f331e2a", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "cf95f18dd8d9b15599e04039b4429cf72237e82e83dd0183ef38f83a32677629", + "start_line": 223, + "name": "context_app_path", + "arity": 2 + }, + "context_base/1:155": { + "line": 155, + "guard": null, + "pattern": "ctx_app", + "kind": "def", + "end_line": 156, + "ast_sha": "4724f5a52e9eeca09932707d22393b4ec90df1d91094fa142f0813ba19a5037c", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "270aa1bc532604c6f5ed45f0215e2e7623bc9e68ef9a581673f0741a5639236f", + "start_line": 155, + "name": "context_base", + "arity": 1 + }, + "context_lib_path/2:242": { + "line": 242, + "guard": "is_atom(ctx_app)", + "pattern": "ctx_app, rel_path", + "kind": "def", + "end_line": 243, + "ast_sha": "92165fc0c821a029281fb08366c2b7cb19979ea753edbaff589826cafe4baac5", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "e43cf004a006ab3f11602bf8d77901efddd62a3b777968d200db8449272b7de4", + "start_line": 242, + "name": "context_lib_path", + "arity": 2 + }, + "context_test_path/2:249": { + "line": 249, + "guard": "is_atom(ctx_app)", + "pattern": "ctx_app, rel_path", + "kind": "def", + "end_line": 250, + "ast_sha": "1e1eeb8e76b1024a1f1859af4ee603ebd5116c4acbd751a231685e9015260019", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "fe7128a2420bf585f526aabe82b3029b511c40743af7d08601700ae778850307", + "start_line": 249, + "name": "context_test_path", + "arity": 2 + }, + "copy_from/4:29": { + "line": 29, + "guard": "is_list(mapping)", + "pattern": "apps, source_dir, binding, mapping", + "kind": "def", + "end_line": 56, + "ast_sha": "a07a0f2dbb73dee0f806e63128d5095ec6f2d0a12ad4f428b1162b5886ec7907", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "136123a9eae4c9f12ead65893f0452d274fcb62cd115914c548d85a2860c9a6b", + "start_line": 29, + "name": "copy_from", + "arity": 4 + }, + "ensure_live_view_compat!/1:388": { + "line": 388, + "guard": null, + "pattern": "generator_mod", + "kind": "def", + "end_line": 393, + "ast_sha": "04cfcb8226395848cab0a44030e66009535a15953b491ba82543c01767ed650f", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "f1db7c92b3f73050794d60e8f5a2db3d77b825ac95c9d14a7b9280349110f06c", + "start_line": 388, + "name": "ensure_live_view_compat!", + "arity": 1 + }, + "eval_from/3:11": { + "line": 11, + "guard": null, + "pattern": "apps, source_file_path, binding", + "kind": "def", + "end_line": 19, + "ast_sha": "1214b31f4a6a027adaeb180207d31bb572cb39f17f3ddbfb6596bb8e6afb862e", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "8a2240307e56e482ee314a3e30ce907e6c44d6aeb2dd411ca5de6306eed00b10", + "start_line": 11, + "name": "eval_from", + "arity": 3 + }, + "fetch_context_app/1:278": { + "line": 278, + "guard": null, + "pattern": "this_otp_app", + "kind": "defp", + "end_line": 307, + "ast_sha": "81f94ca2fb301c1151e65d44d365e9554b9712248e758b92dcff66a765dc3c0b", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "ff889e48f587fd7128774ec6d34db9127868165cc32180a7ecb9f7d57a500664", + "start_line": 278, + "name": "fetch_context_app", + "arity": 1 + }, + "generator_paths/0:193": { + "line": 193, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 193, + "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "e5c17571418d5e5e08ffa13b036e122c84a76d25e7acf6f6fb9e3226fc83cb71", + "start_line": 193, + "name": "generator_paths", + "arity": 0 + }, + "in_umbrella?/1:200": { + "line": 200, + "guard": null, + "pattern": "app_path", + "kind": "def", + "end_line": 204, + "ast_sha": "ae2338907b323fba4094fdd072d00bc7797efcbfc815a46edc8072da98fb5bc3", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "b37f76ff1f891f72dd56e8ec54fbd5ce9de304fa66fcc19605bd7dfe515b94f8", + "start_line": 200, + "name": "in_umbrella?", + "arity": 1 + }, + "inflect/1:104": { + "line": 104, + "guard": null, + "pattern": "singular", + "kind": "def", + "end_line": 122, + "ast_sha": "5ac6eae93ca0ae725b23e31bcf6df485f8680ecd0bdb6c9f078f10ef9e9e6df6", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "cfcd3a1453d58fa8dbf51779336c891b281b999f8452b96106465064d199aae3", + "start_line": 104, + "name": "inflect", + "arity": 1 + }, + "maybe_eex_gettext/2:426": { + "line": 426, + "guard": null, + "pattern": "message, gettext?", + "kind": "defp", + "end_line": 430, + "ast_sha": "16b94429a17d3aed268389c6cd2803f78be402b65c70cc9c64ab557eae06669f", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "3f6320757eb15ace6fdafeb622e9fb9160a3f06ebde9bdbbcec2cbc43a9ab2eb", + "start_line": 426, + "name": "maybe_eex_gettext", + "arity": 2 + }, + "maybe_heex_attr_gettext/2:408": { + "line": 408, + "guard": null, + "pattern": "message, gettext?", + "kind": "defp", + "end_line": 412, + "ast_sha": "9ae782618d093aa0898c5d92dff1cbb59ae4983a041f264e2dcfa0ce3efc447a", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "1a9f2d27c9faac7c22055fb5988fa024c4c3fc6233b105cea62e6b9720aa201a", + "start_line": 408, + "name": "maybe_heex_attr_gettext", + "arity": 2 + }, + "mix_app_path/2:311": { + "line": 311, + "guard": null, + "pattern": "app, this_otp_app", + "kind": "defp", + "end_line": 331, + "ast_sha": "1f26f4d8f54358013eb8a90c220a85e20f788e8e7e8857d63dd08e7a860e3543", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "b1755ecfaf4cbf806e18df2b154105671ce4f5cfc51ad31e934630117ffd4d4f", + "start_line": 311, + "name": "mix_app_path", + "arity": 2 + }, + "modules/0:176": { + "line": 176, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 180, + "ast_sha": "18262def4d3b280822f26ce1e0afd12894e2a57c196b6849e1119d1a0edc15db", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "4007d5ebff0c71cc1ae2ff5e20a7c6155c72e1675d552575acf468185d103193", + "start_line": 176, + "name": "modules", + "arity": 0 + }, + "otp_app/0:169": { + "line": 169, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 170, + "ast_sha": "4c9ab3738894222475fe51a136c497227f1c1a79cf232a46d4bd40f3357508d9", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "7f3b5bd5e1e64c833938c67e1076545c07e6cf4ce760b207de3514aff8855489", + "start_line": 169, + "name": "otp_app", + "arity": 0 + }, + "prepend_newline/1:381": { + "line": 381, + "guard": null, + "pattern": "string", + "kind": "def", + "end_line": 382, + "ast_sha": "544535c6eacb56d67876d3b7ac5a87edc66b45f81428608e13b6516ae4d0f1f5", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "7970ceb5faf1d41646917ca09c410f1bdafbc1d03bb246a74effb9b912f4e481", + "start_line": 381, + "name": "prepend_newline", + "arity": 1 + }, + "prompt_for_conflicts/1:340": { + "line": 340, + "guard": null, + "pattern": "generator_files", + "kind": "def", + "end_line": 361, + "ast_sha": "de64a691ccf69ca4e9f8e8fa96d8b79cd3f0333af74ad3410bdc2c7a1f31a971", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "9d71182a7bbee0073f4f87c303f821c626bb348cf2a0d2cefae36696a40febbc", + "start_line": 340, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "to_app_source/2:62": { + "line": 62, + "guard": "is_binary(path)", + "pattern": "path, source_dir", + "kind": "defp", + "end_line": 63, + "ast_sha": "fe465936bffa922f044e69d236e0f9f40ed3cafc6ed4b106b2eab4862cef5e77", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "3d1ca1cf6979bba11816f92b2bd162eee8a0a050177e289a4fa4849d1465b7e0", + "start_line": 62, + "name": "to_app_source", + "arity": 2 + }, + "to_app_source/2:65": { + "line": 65, + "guard": "is_atom(app)", + "pattern": "app, source_dir", + "kind": "defp", + "end_line": 66, + "ast_sha": "46f18f191a6a250644236b3cbc257e61c32f29f2dbe19794d3595951d78530bd", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "44ca1365cf523abd97d73b07d63f32281426b0d02085806522f1c535c84386be", + "start_line": 65, + "name": "to_app_source", + "arity": 2 + }, + "to_text/1:377": { + "line": 377, + "guard": null, + "pattern": "data", + "kind": "def", + "end_line": 378, + "ast_sha": "fe2da53c644980e24e8c2fa6d2d1d4961f2b68f658322cc7f76124ecf57b72d3", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "f695e7edc75d016604f02f49d5626f0bd50ecfe36013b48a31ddf5c487c92d81", + "start_line": 377, + "name": "to_text", + "arity": 1 + }, + "web_module/1:369": { + "line": 369, + "guard": null, + "pattern": "base", + "kind": "def", + "end_line": 373, + "ast_sha": "9b0cbbb7580d2abdc440403a0443cdd3e6ea5bb6d167471ef8b671ca0a2459a6", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "64321f381c0c178570d1ca0b2fc7a56ae7c65e27506d79030525ba44d69adb4a", + "start_line": 369, + "name": "web_module", + "arity": 1 + }, + "web_path/1:210": { + "line": 210, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 210, + "ast_sha": "83b68980fac0d4765f90a093aa89b7b07a667d058ec886b15720b57bf966f425", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "cdcd028359aea62dd6a0e91b1c82a04912474ca939927dc7c95bd2ce34e54f44", + "start_line": 210, + "name": "web_path", + "arity": 1 + }, + "web_path/2:210": { + "line": 210, + "guard": "is_atom(ctx_app)", + "pattern": "ctx_app, rel_path", + "kind": "def", + "end_line": 216, + "ast_sha": "c6186a5e0983d69be88f30f4b4be6827ba65dd874ee3e2befc9ebf5d9b0ffeed", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "b53f7a66b8253cdf4e320367bb258b32996b81544d0e4762df24d6d765149dd0", + "start_line": 210, + "name": "web_path", + "arity": 2 + }, + "web_test_path/1:268": { + "line": 268, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 268, + "ast_sha": "858f360365ca4991a2c4607fdbb3a0832ceb818ac4b88b6bffb79b24649c9a44", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "0cd82657a14b1cc6e0132c33ff26c92ae7bbe763bf395b79d8d3248aa967fe5b", + "start_line": 268, + "name": "web_test_path", + "arity": 1 + }, + "web_test_path/2:268": { + "line": 268, + "guard": "is_atom(ctx_app)", + "pattern": "ctx_app, rel_path", + "kind": "def", + "end_line": 274, + "ast_sha": "577f15653fc682e9ea5a9b6e4240e5db4097643b3c995ac290eb2de70fc84be8", + "source_file": "lib/mix/phoenix.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", + "source_sha": "725016881915367394bfa87eb280a4bad00fad3dffef4592c8e06ccb72f381f2", + "start_line": 268, + "name": "web_test_path", + "arity": 2 + } + }, + "Mix.Phoenix.Context": { + "file_count/1:84": { + "line": 84, + "guard": null, + "pattern": "%Mix.Phoenix.Context{dir: dir}", + "kind": "def", + "end_line": 88, + "ast_sha": "f42fe19dcac0c043addb81461cb511cbad635e4f9f2668fdcad99ed2aeed3d5c", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "f10897aa34087b150824631ad992f2d5267d0e46bf057218829392bd951df5a0", + "start_line": 84, + "name": "file_count", + "arity": 1 + }, + "function_count/1:70": { + "line": 70, + "guard": null, + "pattern": "%Mix.Phoenix.Context{file: file}", + "kind": "def", + "end_line": 81, + "ast_sha": "2f4a102a98eac99ed9d90175b2b93ae33e2daa3832964ef3270daeb678004856", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "43aaff34a4ea5c7ac16a87aef5367d6e0f1b7f81f69984d2896dcc84c98c208c", + "start_line": 70, + "name": "function_count", + "arity": 1 + }, + "new/2:26": { + "line": 26, + "guard": null, + "pattern": "context_name, opts", + "kind": "def", + "end_line": 27, + "ast_sha": "92b4cf8856c94d635b935f083a79b22a66ae91f7bf22bc1f94fa83733f8ca398", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "4ed27cf2c38de19a4083924f23d385e32715d69b297b236cfaa9d984e80a1fac", + "start_line": 26, + "name": "new", + "arity": 2 + }, + "new/3:30": { + "line": 30, + "guard": null, + "pattern": "context_name, %Mix.Phoenix.Schema{} = schema, opts", + "kind": "def", + "end_line": 60, + "ast_sha": "8912e498b9ff00444cd76f957b686349eaef6a13162f89fc97ed3ff91c3d1963", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "55943d13330670fa6acbbc618e0818a0b6bdbe32f027d7d3a25e1d71c47a9ba8", + "start_line": 30, + "name": "new", + "arity": 3 + }, + "pre_existing?/1:64": { + "line": 64, + "guard": null, + "pattern": "%Mix.Phoenix.Context{file: file}", + "kind": "def", + "end_line": 64, + "ast_sha": "67ac52d54abc7c0cdd8ff2f8bcaeddbd51eb371152a4eb909bff21756bc0bd76", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "88badffed413fd62f1881487dc2b2c05dbcb38634dc4ca820ba469d48f86914c", + "start_line": 64, + "name": "pre_existing?", + "arity": 1 + }, + "pre_existing_test_fixtures?/1:68": { + "line": 68, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_fixtures_file: file}", + "kind": "def", + "end_line": 68, + "ast_sha": "c6dd00dcf15e167c4821737763001ca7842659e9a37de1de6fe68a192916c58c", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "dae4ca3f040325ef007b162166c1e4d52f8235330d63f96c4b7db6a2beee8e2f", + "start_line": 68, + "name": "pre_existing_test_fixtures?", + "arity": 1 + }, + "pre_existing_tests?/1:66": { + "line": 66, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_file: file}", + "kind": "def", + "end_line": 66, + "ast_sha": "28d04e76d472045e9e4b91aa8d396f7b0817cf68da4e399dbdf2bff86c9e3030", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "d549de0ab0de850aa8495b56072af775844bd16fbe6bad4067b4d6cd7b68cab9", + "start_line": 66, + "name": "pre_existing_tests?", + "arity": 1 + }, + "valid?/1:22": { + "line": 22, + "guard": null, + "pattern": "context", + "kind": "def", + "end_line": 23, + "ast_sha": "b3b7d4de52e6a82a51bcd1d17ed349604b1afe374bdbdedcf069ca9eb4bc2cb2", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "ec65fc16f62db1b0c9c22ff34ba28d2ae429607e5a73ff5e39d4f84a9f197f01", + "start_line": 22, + "name": "valid?", + "arity": 1 + }, + "web_module/0:91": { + "line": 91, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 101, + "ast_sha": "ff6b36430b5656cf41d5d8bd6923508e194ce0867811a4e4236de4b2b871154c", + "source_file": "lib/mix/phoenix/context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", + "source_sha": "61c8245b2732da754f9b929c7b4d4264a1dcda196418ffe94aff28517590bc31", + "start_line": 91, + "name": "web_module", + "arity": 0 + } + }, + "Mix.Tasks.Phx.Gen.Context": { + "build/1:145": { + "line": 145, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 145, + "ast_sha": "0799ce3d1f55a6b723fbfb8ec68d13806532b1e9a592ca0a0aa6f58dd1444531", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "b587df70a76d18287d29b4122350c06676205e48db52cdf395ed0d959f93efe9", + "start_line": 145, + "name": "build", + "arity": 1 + }, + "build/2:145": { + "line": 145, + "guard": null, + "pattern": "args, opts", + "kind": "def", + "end_line": 157, + "ast_sha": "2d34ddddd3170a412972ef3cb9acfc56770c1fdd376e1bb8198d0f86ae2a9f39", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "70e7d1a488efd5588bfe82092d9e4c96b5077ffe689b55f2c512a40f818bb4e0", + "start_line": 145, + "name": "build", + "arity": 2 + }, + "copy_new_files/3:187": { + "line": 187, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema} = context, paths, binding", + "kind": "def", + "end_line": 193, + "ast_sha": "85e827c89ab95c5cdac7d5aacf1f11cfa22814e31a313d31e5072b8de91cfa88", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "c86a9b86c6f3d34795963284c776296c7eb540d477238955c0fb270962714a86", + "start_line": 187, + "name": "copy_new_files", + "arity": 3 + }, + "ensure_context_file_exists/3:197": { + "line": 197, + "guard": null, + "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", + "kind": "def", + "end_line": 201, + "ast_sha": "74111f1d9aed09e6246223c54a05eab94a85a8743ef72c890795ac42e5085870", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "7a2a703a9153c447080ea92baa16e1316ea549dd0c3ed02294b8c597033f7184", + "start_line": 197, + "name": "ensure_context_file_exists", + "arity": 3 + }, + "ensure_test_file_exists/3:222": { + "line": 222, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", + "kind": "def", + "end_line": 226, + "ast_sha": "296a06230012831524d0d24674cc3346096800160f909ba68b955588eab35ff0", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "5a6daf026469468506af0c82499494d398ef0f0b5c7c7e542ec05aa6de29b641", + "start_line": 222, + "name": "ensure_test_file_exists", + "arity": 3 + }, + "ensure_test_fixtures_file_exists/3:247": { + "line": 247, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", + "kind": "def", + "end_line": 255, + "ast_sha": "47743768619087b8695ed6a8e59064b9fc66318f7a307aaa1843b911a51bed23", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "0d7975715cf40f1c7e94f198a2f07027e02ce0b74cc07229ae1166c20f03629c", + "start_line": 247, + "name": "ensure_test_fixtures_file_exists", + "arity": 3 + }, + "files_to_be_generated/1:178": { + "line": 178, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema}", + "kind": "def", + "end_line": 180, + "ast_sha": "e007e66bcf44dea5ebd7f0c4d7b428579fe0f203036697e1b5e460ce28fc8854", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "036e7a9813b4594172ed2e965234827c1593dbc7cc9c22e6312b169e33ed3e9d", + "start_line": 178, + "name": "files_to_be_generated", + "arity": 1 + }, + "indent/2:297": { + "line": 297, + "guard": null, + "pattern": "string, spaces", + "kind": "defp", + "end_line": 306, + "ast_sha": "590e92133e87b75da0f7fdd7be1a814f8b3b05a6fe53318f24cbaa1e1933891e", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "c7606eb96c17c56661fbda2cd72f01c8634ef02562e9c1d2985d50bb615f586e", + "start_line": 297, + "name": "indent", + "arity": 2 + }, + "inject_eex_before_final_end/3:311": { + "line": 311, + "guard": null, + "pattern": "content_to_inject, file_path, binding", + "kind": "defp", + "end_line": 325, + "ast_sha": "ef1d47be16b9757c94c28c41e99bd709dcfec6cf5899ea4e1cbf7f2c9f5da431", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "c26df9cedcd5bbb549d4fd18002a4b2bb739e860e2b833f41dbc056ceaf0f525", + "start_line": 311, + "name": "inject_eex_before_final_end", + "arity": 3 + }, + "inject_schema_access/3:206": { + "line": 206, + "guard": null, + "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", + "kind": "defp", + "end_line": 214, + "ast_sha": "77a6bed40a5696b98a0459e7346f6e73f9e7410c8288b6d7905b9aefad7aac73", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "268ea9f81b22bd4b4e5b5b216550b4138905f7049850b0638b07709ca4e8284b", + "start_line": 206, + "name": "inject_schema_access", + "arity": 3 + }, + "inject_test_fixture/3:260": { + "line": 260, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", + "kind": "defp", + "end_line": 272, + "ast_sha": "08d52794de4022ae7951ae3d120219ee77a68276259c90be6f8e9fe5d8f68dab", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "6caad17f91e82ea1a49863973e079c57d781dd4d3eeae30e98dbabdf44c18624", + "start_line": 260, + "name": "inject_test_fixture", + "arity": 3 + }, + "inject_tests/3:231": { + "line": 231, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", + "kind": "defp", + "end_line": 243, + "ast_sha": "9c892396e26a865aa69e31a730a008b86dec161743bbd9576d93b48896c48e66", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "733068849692e90b53cb2a473297ddbe3c770a97ed99d5da815de8311cc44762", + "start_line": 231, + "name": "inject_tests", + "arity": 3 + }, + "maybe_print_unimplemented_fixture_functions/1:275": { + "line": 275, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 292, + "ast_sha": "2bbd03af91b4ac97d88ab92e24b04e9151ecddfa6213d31c289aa1afde5f7b06", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "6d622ce0a01b5a2f12923c0c9ae7b6e49f93188a68e47a65ea71d83b47f5414d", + "start_line": 275, + "name": "maybe_print_unimplemented_fixture_functions", + "arity": 1 + }, + "merge_with_existing_context?/1:453": { + "line": 453, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 476, + "ast_sha": "aabb69f52db446f7ae857e23bf156cb94a34fe2861519a5c1d7e583f979991cd", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "126bf3edd122c7c398c074140f45f975cd6c321a5ad0fedebb2b422cfd91f97f", + "start_line": 453, + "name": "merge_with_existing_context?", + "arity": 1 + }, + "parse_opts/1:160": { + "line": 160, + "guard": null, + "pattern": "args", + "kind": "defp", + "end_line": 168, + "ast_sha": "d7945fb06298f8c7ffc87afccf273d55330129c3ade2529b6244655c6ca34ac9", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "b8123a54ec4f72f3259f14c695c1ff2f31703846c6de7447ad00611f6af54ed9", + "start_line": 160, + "name": "parse_opts", + "arity": 1 + }, + "print_shell_instructions/1:330": { + "line": 330, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema}", + "kind": "def", + "end_line": 332, + "ast_sha": "c6662cdb85d4811bda42fb0728ee1d6f4a0a681161037a46bccb6c4abd9bff22", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "8c67e261d2d3d9bbb7261ee1f0a574e4b893d1f1201172d7a3c154fdffd5b703", + "start_line": 330, + "name": "print_shell_instructions", + "arity": 1 + }, + "prompt_for_code_injection/1:445": { + "line": 445, + "guard": null, + "pattern": "%Mix.Phoenix.Context{generate?: false}", + "kind": "def", + "end_line": 445, + "ast_sha": "84607d6c4899c7e56026195e909b4ffe07cace83c4410a1ccf458b0701040d15", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "3f15bf405c07607f33a83b715a0b77b7770329c121ae41918ce6cf660cbf80c1", + "start_line": 445, + "name": "prompt_for_code_injection", + "arity": 1 + }, + "prompt_for_code_injection/1:447": { + "line": 447, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "def", + "end_line": 449, + "ast_sha": "3d2ba51c2e1734fc19f487e10642086caf4ff5be10a503ec98d059043c898f4b", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "413fa96f2f3af06c3b92bbd84badaee3b2b05351b74edba148f39ca2bb4d6e6d", + "start_line": 447, + "name": "prompt_for_code_injection", + "arity": 1 + }, + "prompt_for_conflicts/1:138": { + "line": 138, + "guard": null, + "pattern": "context", + "kind": "defp", + "end_line": 141, + "ast_sha": "bdb16733bd5f4e623e7ff670421478b975f35e6929f6734cdf134e264001ff47", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "b37e08e41ebe1d8327bba055336126cf15772dc431c6ca55e3ba694a48c5a27a", + "start_line": 138, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "put_context_app/2:171": { + "line": 171, + "guard": null, + "pattern": "opts, nil", + "kind": "defp", + "end_line": 171, + "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", + "start_line": 171, + "name": "put_context_app", + "arity": 2 + }, + "put_context_app/2:173": { + "line": 173, + "guard": null, + "pattern": "opts, string", + "kind": "defp", + "end_line": 174, + "ast_sha": "874ac9aab75cfa76e3340b444da1547cf7af147a21d04d93ab6ef34af30b02e1", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", + "start_line": 173, + "name": "put_context_app", + "arity": 2 + }, + "raise_with_help/1:423": { + "line": 423, + "guard": null, + "pattern": "msg", + "kind": "def", + "end_line": 425, + "ast_sha": "80c89afac535d39230f9a18b436dce7b92af9e05b11b2c6cb76e3238e8b7728e", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "5f7c10c313caa3d8a4aeba153a02ba0759c87d1f7164619a783b2ee39689ec7f", + "start_line": 423, + "name": "raise_with_help", + "arity": 1 + }, + "run/1:112": { + "line": 112, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 135, + "ast_sha": "06fb3783f2d5f59f0fd15a5c60b5273cb28a54476e111bdc71a90fc144dd2fc5", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "42c1ac42b3355208120cd1147ed950ec176a28b6a71d34029a5d1a5ff8093ccd", + "start_line": 112, + "name": "run", + "arity": 1 + }, + "schema_access_template/1:338": { + "line": 338, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema}", + "kind": "defp", + "end_line": 349, + "ast_sha": "b506d197c899ca8bbad89bf92ad993002b27397b9301801454dcd0ef0ef2d2bf", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "dcebdc07b0c6e8cea42bf99df1ee5c4427eb19ddf211fe9c710dc881cafa007d", + "start_line": 338, + "name": "schema_access_template", + "arity": 1 + }, + "singularize/2:480": { + "line": 480, + "guard": null, + "pattern": "1, plural", + "kind": "defp", + "end_line": 480, + "ast_sha": "c205a443ba79e93ea64d30233e45ea81a1d58787185cc5807dc17808dd884297", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "7e139b39740c28b370bc3bd64809a73e27a72ad064c27c162699656fa6e8ec06", + "start_line": 480, + "name": "singularize", + "arity": 2 + }, + "singularize/2:481": { + "line": 481, + "guard": null, + "pattern": "amount, plural", + "kind": "defp", + "end_line": 481, + "ast_sha": "7710d0c6148d214693dc65f6249e9ea01bc76ffb30cf0f8721b2d024ff3cc91d", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "9c04b845fe2b8621c657ef5f3b7b4e8292a2e03059612e7478d025513d049260", + "start_line": 481, + "name": "singularize", + "arity": 2 + }, + "validate_args!/3:354": { + "line": 354, + "guard": null, + "pattern": "[maybe_context_name, schema_name_or_plural, plural_or_first_attr | schema_args], optional, help", + "kind": "defp", + "end_line": 414, + "ast_sha": "8650faa9936e3be738964837bf8d5ec4522a80c8ab99679fa158da5a97b7883c", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "f449a8397ada78a559d099d85a817b6987a0878f3506a71bcb9e515908e9f183", + "start_line": 354, + "name": "validate_args!", + "arity": 3 + }, + "validate_args!/3:418": { + "line": 418, + "guard": null, + "pattern": "_, _, help", + "kind": "defp", + "end_line": 419, + "ast_sha": "9e123290bc6df2f5d70840d41e9f504b38919192546e047da938caa9d8368902", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "b268709a37013321d79bf8d315de480b8ed7ce2dbfb21746f67477830ad21a1f", + "start_line": 418, + "name": "validate_args!", + "arity": 3 + }, + "write_file/2:217": { + "line": 217, + "guard": null, + "pattern": "content, file", + "kind": "defp", + "end_line": 218, + "ast_sha": "ba947015abd9bcb81b56a619de387926c984cf8f48f12339c2ad5ad26a6aa770", + "source_file": "lib/mix/tasks/phx.gen.context.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", + "source_sha": "6c52e1d76cb17916a120f205049f0892b4f18681feefb06f2a403c02f17e253d", + "start_line": 217, + "name": "write_file", + "arity": 2 + } + }, + "Phoenix.Token": { + "decrypt/3:244": { + "line": 244, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 244, + "ast_sha": "a8ef2af15bc5b42d6892274ca90ef1f5426fab435ca56b74742675d34c4dcd9c", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "babdf23300fc4a6a6e6510c11fc9882ded5975d74c06fd882015a03a9e94fdbe", + "start_line": 244, + "name": "decrypt", + "arity": 3 + }, + "decrypt/4:244": { + "line": 244, + "guard": "is_binary(secret)", + "pattern": "context, secret, token, opts", + "kind": "def", + "end_line": 247, + "ast_sha": "37437803101785e59dae8d6a35e9642d65d737c9adbc5e829fbc213d14a1d0df", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "75463726383d1a66a8633ad2a2c7d776bda38abf07fc4f4cd366ae9ac0d2ac28", + "start_line": 244, + "name": "decrypt", + "arity": 4 + }, + "encrypt/3:159": { + "line": 159, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 159, + "ast_sha": "0e16fbbb3fb6bf0e093149a247a0283b32c5e02ad11d346418c08a1d0763371c", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "539c1628c76c6d324e73ec43ffac14ef19f780a976d8fbd14473f95a91d32bc1", + "start_line": 159, + "name": "encrypt", + "arity": 3 + }, + "encrypt/4:159": { + "line": 159, + "guard": "is_binary(secret)", + "pattern": "context, secret, data, opts", + "kind": "def", + "end_line": 162, + "ast_sha": "710cd615fb654fa966cba35a23b7a09a8fa25e9b68fdc45dbb6b3f3e6875f060", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "69c0720a773ac140196696ea28fd61abe68eaf833d97f1f2f72319226bdee60f", + "start_line": 159, + "name": "encrypt", + "arity": 4 + }, + "get_endpoint_key_base/1:264": { + "line": 264, + "guard": null, + "pattern": "endpoint", + "kind": "defp", + "end_line": 267, + "ast_sha": "c2eca5589311219e65e778884a4b88592d878d967ce29c6c4d6b68e94d1d786e", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "977e6ac94c6493696ede0aa0d86715d048cb8a8d722dc9e06936b57a179ccc72", + "start_line": 264, + "name": "get_endpoint_key_base", + "arity": 1 + }, + "get_key_base/1:252": { + "line": 252, + "guard": null, + "pattern": "%Plug.Conn{} = conn", + "kind": "defp", + "end_line": 253, + "ast_sha": "5008a20c4515179cf0bba3393fcfb1745d1e03d39272ed2e744cf50bd2221659", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "eeb3f9bc48b32182209f4eef3af9d3c32bb2ad0da08555f7a983f234ad860472", + "start_line": 252, + "name": "get_key_base", + "arity": 1 + }, + "get_key_base/1:255": { + "line": 255, + "guard": null, + "pattern": "%_{endpoint: endpoint}", + "kind": "defp", + "end_line": 256, + "ast_sha": "165477dec0b3e0a63c0661924518100b358b833e34affade066eb495720e161f", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "df87a6bd56205db0f58adfabf9f6062ab0d5528ba233bee8e44398ac298538f8", + "start_line": 255, + "name": "get_key_base", + "arity": 1 + }, + "get_key_base/1:258": { + "line": 258, + "guard": "is_atom(endpoint)", + "pattern": "endpoint", + "kind": "defp", + "end_line": 259, + "ast_sha": "a3a9e4e70087080678fc9071c051aaf0d0397fa6029dfa33b9af05405bacef81", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "2a8eee5a9c2269982ac63b46455dcf5df7938e40bd29b8bfea4990c10d57d93c", + "start_line": 258, + "name": "get_key_base", + "arity": 1 + }, + "get_key_base/1:261": { + "line": 261, + "guard": "is_binary(string) and byte_size(string) >= 20", + "pattern": "string", + "kind": "defp", + "end_line": 262, + "ast_sha": "a4f827a384ff1650ca35f3785e36d7242b1f7fa21c4bafb7827a458556e6a254", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "51711452f25ce864d803f915a9bdd7e10e230305f3fd29cb38c03a5bc83ea58f", + "start_line": 261, + "name": "get_key_base", + "arity": 1 + }, + "sign/3:133": { + "line": 133, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 133, + "ast_sha": "756433e8022dd4a2ca08cddeb4bd423b73d3d2d806ee96ea6416b3e5d5d93ee4", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "0f286dd0ff32bc2498e4544b84f1dd007dd0e337b4b228cf0b7f15326a8da7f2", + "start_line": 133, + "name": "sign", + "arity": 3 + }, + "sign/4:133": { + "line": 133, + "guard": "is_binary(salt)", + "pattern": "context, salt, data, opts", + "kind": "def", + "end_line": 136, + "ast_sha": "63f45948292a1019cf76b58463f64d8d72dbb578d02e22b1732e731fbd9bbf42", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "1d67ff6e4315ceba6bb9f20b0cd34ae551b467ab5dfda37429186446df738f6a", + "start_line": 133, + "name": "sign", + "arity": 4 + }, + "verify/3:220": { + "line": 220, + "guard": null, + "pattern": "x0, x1, x2", + "kind": "def", + "end_line": 220, + "ast_sha": "7e7cb4bf462b45803283fa18c0c7775bedd7f6903cdf37f4426b73023cc7acc4", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "5380d3fa6a2b1f6189115c62f30324b67d157ab45f6e5ab16ee90c4ec3cc01a3", + "start_line": 220, + "name": "verify", + "arity": 3 + }, + "verify/4:220": { + "line": 220, + "guard": "is_binary(salt)", + "pattern": "context, salt, token, opts", + "kind": "def", + "end_line": 223, + "ast_sha": "259bb8e2d7cb192e98afaf7431297d99f1b8e11706e5dcad3fdf0d43da5e00b7", + "source_file": "lib/phoenix/token.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", + "source_sha": "514bb74124b35e0eb752137fe5c0aa24c7c694faccbb74444e2a6117edaea580", + "start_line": 220, + "name": "verify", + "arity": 4 + } + }, + "Phoenix.Router.Scope": { + "update_attribute/3:299": { + "line": 299, + "guard": null, + "pattern": "module, attr, fun", + "kind": "defp", + "end_line": 300, + "ast_sha": "2340fbb7a55c23a8ef2116e158f9f300fcf95f415124ea173819fe459792a5d6", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "384e6712c615224092989c81abe1a888e8348c0569e594595c93f1d4cfb6af2f", + "start_line": 299, + "name": "update_attribute", + "arity": 3 + }, + "pop/1:223": { + "line": 223, + "guard": null, + "pattern": "module", + "kind": "def", + "end_line": 226, + "ast_sha": "307153ab1ef0c62cdb416e0a8ba3fd760f30fe784cd0b9977bee8bc8b1d87ad9", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "8317ba7d753bb11c4b471119b3e6f7a3fd67bf14a77e01c79c548d72672b076d", + "start_line": 223, + "name": "pop", + "arity": 1 + }, + "pipeline/2:114": { + "line": 114, + "guard": "is_atom(pipe)", + "pattern": "module, pipe", + "kind": "def", + "end_line": 115, + "ast_sha": "103073a29e2fef35c9e6468b6c35130037554c90f267b31d0b593f34e430a982", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "b2a86fac1c2fbf15979f1fb161048101fca2dbb53e76da0c0517a101439e2735", + "start_line": 114, + "name": "pipeline", + "arity": 2 + }, + "validate_hosts!/1:194": { + "line": 194, + "guard": null, + "pattern": "nil", + "kind": "defp", + "end_line": 194, + "ast_sha": "410d7b6b887436685793fbe282c1e142752de50dd78b8e1c5709a32e7e55842a", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "ec0ba4f3e1ca108f09de5d705ccef7862b1396c3f9734021e40b26976a9bb6ad", + "start_line": 194, + "name": "validate_hosts!", + "arity": 1 + }, + "full_path/2:240": { + "line": 240, + "guard": null, + "pattern": "module, path", + "kind": "def", + "end_line": 247, + "ast_sha": "f2c8c771e41f8a90469857db07d36dac1a7e3bb7bcc9af56bbe6158f9226a801", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "acc4ee0f373389734b9f0a86b268feb3dff98fb4c7faac4978bc960382ef8c1f", + "start_line": 240, + "name": "full_path", + "arity": 2 + }, + "put_top/2:289": { + "line": 289, + "guard": null, + "pattern": "module, value", + "kind": "defp", + "end_line": 291, + "ast_sha": "2db8dfe4dea8e4940271aeb73f92b1f44904828d2991be4f71ff2f09ea697675", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "00fb79fa05969cab4d964c0c2e8d7add2cc5019a32cc0fc508a9428294053927", + "start_line": 289, + "name": "put_top", + "arity": 2 + }, + "join_path/2:263": { + "line": 263, + "guard": null, + "pattern": "top, path", + "kind": "defp", + "end_line": 264, + "ast_sha": "f586374891a1a893e9e6f42f8be2c6d6815f53cae98f876996916ac38c8ba78c", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "df51d1136a1f25baf9d6c7119226f95115f94daeb68efc49110704a7b50502ad", + "start_line": 263, + "name": "join_path", + "arity": 2 + }, + "push/2:137": { + "line": 137, + "guard": "is_binary(path)", + "pattern": "module, path", + "kind": "def", + "end_line": 138, + "ast_sha": "17e9fd462203af661a09b4a87ba3272e8d63e86aa8fb8fef32020aed886ad2c1", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "f8f55625509b97974d4daf817720e40e2a73a89e9723403e5a28c8ed826fe4d8", + "start_line": 137, + "name": "push", + "arity": 2 + }, + "validate_path/1:107": { + "line": 107, + "guard": null, + "pattern": "path", + "kind": "def", + "end_line": 108, + "ast_sha": "451b0f2ca971ea0a11e75f9b6bf078340f32ead53b4929e4515c1592952fe60b", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "0649c59cbc02920f6b654532d920c092135f4797657293949c9635080f80bd8f", + "start_line": 107, + "name": "validate_path", + "arity": 1 + }, + "validate_forward!/2:93": { + "line": 93, + "guard": null, + "pattern": "_, plug", + "kind": "defp", + "end_line": 94, + "ast_sha": "32bbe56cbbf9d8d376766f2191b9c6b7fec3c39bd84c1cfeadeca577ca54d6c3", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "0b59f2f2606d5459ba8ecf2cbf612339adaa59f83a23ebad9c5cfdb4cf0c3ada", + "start_line": 93, + "name": "validate_forward!", + "arity": 2 + }, + "init/1:22": { + "line": 22, + "guard": null, + "pattern": "module", + "kind": "def", + "end_line": 25, + "ast_sha": "3f21752e9a90981459b3eef8f37fd207bd44ea78379aeaaa7bec39f2902aa15f", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "32b81ec0261e0c809e1043dedc1f7d427b4bef6587bd3751c20b06a925dbca80", + "start_line": 22, + "name": "init", + "arity": 1 + }, + "deprecated_trailing_slash/2:178": { + "line": 178, + "guard": null, + "pattern": "opts, top", + "kind": "defp", + "end_line": 190, + "ast_sha": "54605f27e04f9f66c9eb6149de5d34ca2c9c372e4ad8b4abc488579effe40b18", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "c03554b766737eed27994a1b42e299fc40dba54a479661e236440f2a7b661823", + "start_line": 178, + "name": "deprecated_trailing_slash", + "arity": 2 + }, + "join_as/2:274": { + "line": 274, + "guard": null, + "pattern": "_top, nil", + "kind": "defp", + "end_line": 274, + "ast_sha": "e2cc470835c15ca6003dcf0777f19c70d798b0da8c12a2d2560d44cf1f420ddf", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "40a3053ec120def3d64d2ac21b15ab1eda42804213c5e15531aa57cb633377d4", + "start_line": 274, + "name": "join_as", + "arity": 2 + }, + "join/7:251": { + "line": 251, + "guard": null, + "pattern": "top, path, alias, alias?, as, private, assigns", + "kind": "defp", + "end_line": 260, + "ast_sha": "9b1e57429d25e46c1cfd7636a6f9216d65400fae0145b49c7f5d932564170e44", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "9924f2210bed4618dd9945af736373df315d97a530b76ba9a94fb18a574c81b6", + "start_line": 251, + "name": "join", + "arity": 7 + }, + "__struct__/1:9": { + "line": 9, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 9, + "ast_sha": "5c01bfd9ec8e0c9fd7242c7bce0eee04b1e82fb225a09e7d266ba30ada11118b", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "acf16f4224198d313a058c19bec3cfc66d8da096fb4c14be3f74dc717d9ad6aa", + "start_line": 9, + "name": "__struct__", + "arity": 1 + }, + "validate_path/1:102": { + "line": 102, + "guard": "is_binary(path)", + "pattern": "path", + "kind": "def", + "end_line": 104, + "ast_sha": "78a5d4c8db73b770bc4f4e525160911eaa9b6fecb22e75ed00966af79a97f0a2", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "35e571e2e4e2e4e79d23edc17d95abcf2b98459f2fd32a15f748b43bcc0c5d58", + "start_line": 102, + "name": "validate_path", + "arity": 1 + }, + "__struct__/0:9": { + "line": 9, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 9, + "ast_sha": "c7d65aa1e58bf7143c55084b1b139e62e75f19ac4d6db446aada065829dfb1a5", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "acf16f4224198d313a058c19bec3cfc66d8da096fb4c14be3f74dc717d9ad6aa", + "start_line": 9, + "name": "__struct__", + "arity": 0 + }, + "route/8:31": { + "line": 31, + "guard": null, + "pattern": "line, module, kind, verb, path, plug, plug_opts, opts", + "kind": "def", + "end_line": 78, + "ast_sha": "780fc5ffcadecfaf3257b110a08edf3b59946c90090c20017e2a7f4ea026ccb7", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "af4ecb9231d083355a2a8b3017640c30c75e5bac6d7b5743e7a981ffe6f51392", + "start_line": 31, + "name": "route", + "arity": 8 + }, + "raise_invalid_host/1:207": { + "line": 207, + "guard": null, + "pattern": "host", + "kind": "defp", + "end_line": 209, + "ast_sha": "e44b24cefb784464d30d82e82e3d3152eb77a53b718162cf180c2913b2215ac2", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "ba42d3bc2aaa57fba69f0da787252eaf09af551ba28ed94c840f393593f6923d", + "start_line": 207, + "name": "raise_invalid_host", + "arity": 1 + }, + "push/2:141": { + "line": 141, + "guard": "is_list(opts)", + "pattern": "module, opts", + "kind": "def", + "end_line": 174, + "ast_sha": "940396795e82a4825b3b7d5932e2002b14d45696948c07a764b89129d8db6871", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "157ae5a1cc26a254429ee51a6105d3e5bc67287c0d872c8e8c747d345eb65f39", + "start_line": 141, + "name": "push", + "arity": 2 + }, + "validate_path/1:100": { + "line": 100, + "guard": null, + "pattern": "<<\"/\"::binary, _::binary>> = path", + "kind": "def", + "end_line": 100, + "ast_sha": "d32fb7ff229635de38d0fc2fcbe1399f389732426a9cc234347a1ffe9f9fa9b9", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "03223e63a1c79fea5bb1af00c4865987ea4408a5fbabbc43b749ee2a325d04ad", + "start_line": 100, + "name": "validate_path", + "arity": 1 + }, + "pipe_through/2:121": { + "line": 121, + "guard": null, + "pattern": "module, new_pipes", + "kind": "def", + "end_line": 131, + "ast_sha": "ea5ef91a0bdaf9f480aaa6f3df4fa162b518cf00bb84c30aa9ab07c4e08405cd", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "90f145ba87099a9fbee806babebaf550b83be56f9e386f84c17d69ca5f45a9cc", + "start_line": 121, + "name": "pipe_through", + "arity": 2 + }, + "append_unless_false/4:212": { + "line": 212, + "guard": null, + "pattern": "top, opts, key, fun", + "kind": "defp", + "end_line": 216, + "ast_sha": "685bf3680de4651fe2783a897822038d003456e860e411aa334afe3a46586e1d", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "1ef9681ddf27c3fb9e7b00fbde2e5dc5489f3a806eb5387ad62eca39ad2dd93d", + "start_line": 212, + "name": "append_unless_false", + "arity": 4 + }, + "validate_hosts!/1:195": { + "line": 195, + "guard": "is_binary(host)", + "pattern": "host", + "kind": "defp", + "end_line": 195, + "ast_sha": "64098d07779f680098ab87e0fa6de37fb77fbbea2480b85b1a7143a908e4fd8a", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "e5488b7e3ff85db8f90c634f3787ce47784629c5388b3e63a965714c810443ac", + "start_line": 195, + "name": "validate_hosts!", + "arity": 1 + }, + "update_pipes/2:285": { + "line": 285, + "guard": null, + "pattern": "module, fun", + "kind": "defp", + "end_line": 286, + "ast_sha": "ffa2ba412fb927d6606c7dc5a83bdb0bae6becb65c6a3d97f7437be23913d140", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "7566cadc2f48701be70ada3f898b7711a30f17abb686ffd27c9dc6c233860715", + "start_line": 285, + "name": "update_pipes", + "arity": 2 + }, + "validate_forward!/2:82": { + "line": 82, + "guard": "is_atom(plug)", + "pattern": "path, plug", + "kind": "defp", + "end_line": 89, + "ast_sha": "5df6cef865a39a7a1f359a9ac2f12b56b55a25c75992d84e89f8879500289a70", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "86b72de49ef6afd4a82d2b116c11c16ee48afa18281686e1ad60b7234713acf7", + "start_line": 82, + "name": "validate_forward!", + "arity": 2 + }, + "get_top/1:277": { + "line": 277, + "guard": null, + "pattern": "module", + "kind": "defp", + "end_line": 278, + "ast_sha": "09673d46960a03022645540eca59124b9e1f4886433331dc9f9ee8cc624ff87c", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "3688485e0d6a1590dad34dbc712ce953c81355e31964b3056f33f83ff524c549", + "start_line": 277, + "name": "get_top", + "arity": 1 + }, + "validate_hosts!/1:197": { + "line": 197, + "guard": "is_list(hosts)", + "pattern": "hosts", + "kind": "defp", + "end_line": 201, + "ast_sha": "e4e0b35e2e67ea00bec929df96c449423db829611e7b9312367afeeb9b132bb7", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "a3ad4b87b3fe8dec163927918305116ce452d87698b95b9d5835f3c0a51d55cb", + "start_line": 197, + "name": "validate_hosts!", + "arity": 1 + }, + "expand_alias/2:233": { + "line": 233, + "guard": null, + "pattern": "module, alias", + "kind": "def", + "end_line": 234, + "ast_sha": "179ce5ac5d96e3364056b1ba36ee07d442fb6a17aac40cb1168fa04e56b600b2", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "d9ab4ca8c3d3c3ad06c1f58e526511975603d05ee315b6bfe542c8979894810c", + "start_line": 233, + "name": "expand_alias", + "arity": 2 + }, + "join_alias/2:267": { + "line": 267, + "guard": "is_atom(alias)", + "pattern": "top, alias", + "kind": "defp", + "end_line": 270, + "ast_sha": "36762c9dbf5b2a40eac4abafc55b11cc60aea1eb1d2566402df6a219059b155d", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "dcf3c951de2c554bc2db76d098813917b600cccf00a620b3b72da0e2d071cbc5", + "start_line": 267, + "name": "join_alias", + "arity": 2 + }, + "update_stack/2:281": { + "line": 281, + "guard": null, + "pattern": "module, fun", + "kind": "defp", + "end_line": 282, + "ast_sha": "f40bc4d171854a25fc63988ad5b7d010b51e1ddaa8a7f1c5aed76cddaa37543f", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "67b664dc77121628cc772b1e8eac7c9a8c065e59a294b146831ad4eef507c3c0", + "start_line": 281, + "name": "update_stack", + "arity": 2 + }, + "get_attribute/2:294": { + "line": 294, + "guard": null, + "pattern": "module, attr", + "kind": "defp", + "end_line": 296, + "ast_sha": "9aa07cdd21291bbdfd174e120a91a1e49e948bf1ec43c104be6fdbc773d08eff", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "d360eeb3782cb9a85e83ddeb7df4187918bb5eeb510bd02107a9c02abbb6ebe8", + "start_line": 294, + "name": "get_attribute", + "arity": 2 + }, + "join_as/2:275": { + "line": 275, + "guard": "is_atom(as) or is_binary(as)", + "pattern": "top, as", + "kind": "defp", + "end_line": 275, + "ast_sha": "d369fc9a9671c77722913383992a17fa97b03003baa220206bd7adce940198ea", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "a96e42a2f6be3dabce512d61a05c3e27c71c717d624b721dc6a58b687164ab9c", + "start_line": 275, + "name": "join_as", + "arity": 2 + }, + "validate_hosts!/1:205": { + "line": 205, + "guard": null, + "pattern": "invalid", + "kind": "defp", + "end_line": 205, + "ast_sha": "aa4ba2f954444c36ebd10f4d836a5a95a5fae698a5839d558099776680c1c335", + "source_file": "lib/phoenix/router/scope.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", + "source_sha": "473d546c258ef0a798b62122f379490e96eecff86d1922d1b73b0de3fc8eb079", + "start_line": 205, + "name": "validate_hosts!", + "arity": 1 + } + }, + "Phoenix.Router.Route": { + "__struct__/0:28": { + "line": 28, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 28, + "ast_sha": "1617fb7eb06b3609f8e7b574946b49fcf9395ace039a75d4d9e861af7551ac41", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "5995dc95aeec0f228d6726cb38c22b689fb1422338cc6bd6f2aabfed4059c3d0", + "start_line": 28, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:28": { + "line": 28, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 28, + "ast_sha": "4f7bdbbd1a8932d21c43cbd62bb23b59a71d33e83aded47a829afaf2f4b9c169", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "5995dc95aeec0f228d6726cb38c22b689fb1422338cc6bd6f2aabfed4059c3d0", + "start_line": 28, + "name": "__struct__", + "arity": 1 + }, + "build/14:79": { + "line": 79, + "guard": "is_atom(verb) and is_list(hosts) and is_atom(plug) and (is_binary(helper) or helper == nil) and\n is_list(pipe_through) and is_map(private) and is_map(assigns) and is_map(metadata) and\n (=:=(kind, :match) or =:=(kind, :forward)) and is_boolean(trailing_slash?)", + "pattern": "line, kind, verb, path, hosts, plug, plug_opts, helper, pipe_through, private, assigns, metadata, trailing_slash?, warn_on_verify?", + "kind": "def", + "end_line": 114, + "ast_sha": "6c0dc4dc2075dd6f578027fc7927acd59d07ebeb482d60396348da8dce669294", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "8929cd7fe5b53191141dfade35ecb58c1366f08fd6324135ef6507f442314d3b", + "start_line": 79, + "name": "build", + "arity": 14 + }, + "build_dispatch/1:194": { + "line": 194, + "guard": null, + "pattern": "%Phoenix.Router.Route{kind: :match, plug: plug, plug_opts: plug_opts}", + "kind": "defp", + "end_line": 196, + "ast_sha": "04ad205a7abcdcfd6b31618c901b1585792863d911c8042a83d9a06cf00f7bab", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "0faf8012e1d9a810cc8d4fc4aa3ba9029c0c43f8f11a36a11527800c8473c6e9", + "start_line": 194, + "name": "build_dispatch", + "arity": 1 + }, + "build_dispatch/1:200": { + "line": 200, + "guard": null, + "pattern": "%Phoenix.Router.Route{kind: :forward, plug: plug, plug_opts: plug_opts, metadata: metadata}", + "kind": "defp", + "end_line": 209, + "ast_sha": "18c72a41139259b776c34d76f79990fb411eb00900ccf09ae61d76baf5ce2d43", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "645a7acef0483dc169fd15716254e86d1fb5e9180776c9ccfb1c9e6af016f0fb", + "start_line": 200, + "name": "build_dispatch", + "arity": 1 + }, + "build_host_match/1:135": { + "line": 135, + "guard": null, + "pattern": "[]", + "kind": "def", + "end_line": 135, + "ast_sha": "828146fbc543280a3d1eeb068ed69b99f975799e0e6d6a08c14c20e57fc54629", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "1f5d48c7a5864439542dede555b77c782cec79a075ea0e0eb1df1721bf7ab800", + "start_line": 135, + "name": "build_host_match", + "arity": 1 + }, + "build_host_match/1:137": { + "line": 137, + "guard": null, + "pattern": "[_ | _] = hosts", + "kind": "def", + "end_line": 138, + "ast_sha": "b202ec3e70e9206bd51280a10837704f790fdf32cafbdbb07312257686d2455f", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "a710acc3af3a27530602ba447d5c5045411975e985bd169fddfdfabe4aa4f362", + "start_line": 137, + "name": "build_host_match", + "arity": 1 + }, + "build_params/0:214": { + "line": 214, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 223, + "ast_sha": "a809642cdda0f3a91ed65a46c37d37fb41a7f3dd3e26db004425c1b981a7c413", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "e1d9e5b227551cb4f23bc1295ff991bdcde2bf32860fb85617ea0f0130167bd1", + "start_line": 214, + "name": "build_params", + "arity": 0 + }, + "build_path_and_binding/1:146": { + "line": 146, + "guard": null, + "pattern": "%Phoenix.Router.Route{path: path} = route", + "kind": "defp", + "end_line": 153, + "ast_sha": "561d3ef406e023606c89aa03e90988c6e167d4e61e440bd7886d32959e3bea79", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "3856da158ccb0e4270c58832681e9bd0905a42093d8d5e465350def907673b30", + "start_line": 146, + "name": "build_path_and_binding", + "arity": 1 + }, + "build_path_params/1:144": { + "line": 144, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 144, + "ast_sha": "28db94cabd97180b73363b1ae2df99af033543710e5a96fe3d1f70b4f7fa2ff4", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "d4fb02a720e15aa51746253a8df649ac82f572f34d969a0b48b8e2a966e0561c", + "start_line": 144, + "name": "build_path_params", + "arity": 1 + }, + "build_prepare/1:172": { + "line": 172, + "guard": null, + "pattern": "route", + "kind": "defp", + "end_line": 182, + "ast_sha": "6c2ba511926ceb7fb5286e86a09629387520a1f0911bdd696492ff330aadcce7", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "6517ea6745d74104848ca6964ce6a1e5de05dbcd50df5461285d4f9a4e1ed5e5", + "start_line": 172, + "name": "build_prepare", + "arity": 1 + }, + "build_prepare_expr/2:186": { + "line": 186, + "guard": "data == %{}", + "pattern": "_key, data", + "kind": "defp", + "end_line": 186, + "ast_sha": "93e00ce13702c0e1d893237dcf6cca580a0946e89e62a3ce593b27d9763d7558", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "2210f7e47d37e530d094feebf993d17ddfcc281d4631cfca83af9d93cdafdf32", + "start_line": 186, + "name": "build_prepare_expr", + "arity": 2 + }, + "build_prepare_expr/2:188": { + "line": 188, + "guard": null, + "pattern": "key, data", + "kind": "defp", + "end_line": 191, + "ast_sha": "8e3eaa072b90a17d0ddb60dd38a6a078244b8ddff49efa8697f3986e8e90972c", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "3c86ae9bad5b07cf81ef703e53e11591fd509e8d9b519b05f14b74478a5d0dfa", + "start_line": 188, + "name": "build_prepare_expr", + "arity": 2 + }, + "call/2:51": { + "line": 51, + "guard": null, + "pattern": "%{path_info: path, script_name: script} = conn, {fwd_segments, plug, opts}", + "kind": "def", + "end_line": 56, + "ast_sha": "f4849fc0d1e48803e9e9d5b4353fd309f7c9829f65a601215e2ee73e3652fa6f", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "f7f1235ecf41754c131e16caedbfaa610af0e8afbbb15eec02cb1b298fb8628b", + "start_line": 51, + "name": "call", + "arity": 2 + }, + "exprs/1:121": { + "line": 121, + "guard": null, + "pattern": "route", + "kind": "def", + "end_line": 131, + "ast_sha": "102aee2d246ae1e65d4117d69fad99724e25a20df75207e6bc57c1e836911a58", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "4c3170bfba67e2b1d5b2f86f10c946b0b946872a9c87800902e380cd765e846f", + "start_line": 121, + "name": "exprs", + "arity": 1 + }, + "init/1:48": { + "line": 48, + "guard": null, + "pattern": "opts", + "kind": "def", + "end_line": 48, + "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", + "start_line": 48, + "name": "init", + "arity": 1 + }, + "merge_params/2:230": { + "line": 230, + "guard": null, + "pattern": "%Plug.Conn.Unfetched{}, path_params", + "kind": "def", + "end_line": 230, + "ast_sha": "11fb868a8ebb3179e0a296dff8315db936294a61478f3f8009076d9c76153dc6", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "77ead829f49a6f6303ceb853903d6582bdb3d18dcfe35fe1e2ff1353fec079e5", + "start_line": 230, + "name": "merge_params", + "arity": 2 + }, + "merge_params/2:231": { + "line": 231, + "guard": null, + "pattern": "params, path_params", + "kind": "def", + "end_line": 231, + "ast_sha": "6556a9d5f9c92a99bd5308e4a9794978563beadbc99690ef1eb6c688d985fe12", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "eb51d87be5431d8cd406b8820c4cd978398aa07f4a3ed509ee6dd478ad55f329", + "start_line": 231, + "name": "merge_params", + "arity": 2 + }, + "rewrite_segments/1:157": { + "line": 157, + "guard": null, + "pattern": "segments", + "kind": "defp", + "end_line": 169, + "ast_sha": "e8a90ed4cb58f2ad1e85f83ad05f9af8786b20083a4e36ba30a7525223fce09d", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "369c260d4d8f849e9d14cbe9fad7d397e8f2d550bc778fae455be4441cd4f145", + "start_line": 157, + "name": "rewrite_segments", + "arity": 1 + }, + "verb_match/1:141": { + "line": 141, + "guard": null, + "pattern": ":*", + "kind": "defp", + "end_line": 141, + "ast_sha": "4fe21c9b344c2b8374001eef8fa51ae5ee88437a47e7d7e9fb691df49db22d56", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "2a3fda9568a9e79c8ca9e7073454ac8db27b91f7d6e566c87a4ab7f65b1ab2a6", + "start_line": 141, + "name": "verb_match", + "arity": 1 + }, + "verb_match/1:142": { + "line": 142, + "guard": null, + "pattern": "verb", + "kind": "defp", + "end_line": 142, + "ast_sha": "d063e01b6975750cda82c403ea799358ea2dc469df1dce62aea7d0ff30867c22", + "source_file": "lib/phoenix/router/route.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", + "source_sha": "6d96631db8f69c1109ac9e0d9dee51d57b2043d13775eafa6311cd1a3b024801", + "start_line": 142, + "name": "verb_match", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Auth": { + "datetime_now/1:1126": { + "line": 1126, + "guard": null, + "pattern": "%{timestamp_type: :naive_datetime}", + "kind": "defp", + "end_line": 1126, + "ast_sha": "ab7cef9e0b77edfc0287b98b471c814a2b1d411dec87878408839449497e9c43", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "5a5ff452e447ae0caf11367406061a4ebbd8c238ba46b9e1e83e9f6ae73f57ac", + "start_line": 1126, + "name": "datetime_now", + "arity": 1 + }, + "build_hashing_library!/1:312": { + "line": 312, + "guard": null, + "pattern": "opts", + "kind": "defp", + "end_line": 322, + "ast_sha": "2852cdcd226c514579055a7afcee9c89b3df5b2ef7f304e9e622d52ad38fffb0", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "25a225ec94f083432c8cece7b3041e03f5d5b63a2a231ad028a223e6518b9d90", + "start_line": 312, + "name": "build_hashing_library!", + "arity": 1 + }, + "run/2:174": { + "line": 174, + "guard": null, + "pattern": "args, test_opts", + "kind": "def", + "end_line": 251, + "ast_sha": "29e22ca550f9c4034d99d34c1a41b3e7683e819fbda3b5bbc1279f6ea505efb8", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "0051de608d832b8ffac2fc25e32bac7f21491247fc47d4ead6c9d6c4ab4bd175", + "start_line": 174, + "name": "run", + "arity": 2 + }, + "datetime_module/1:1123": { + "line": 1123, + "guard": null, + "pattern": "%{timestamp_type: :utc_datetime}", + "kind": "defp", + "end_line": 1123, + "ast_sha": "4a9dc74f18102c0cbe096400d66368e8ba1c8af62a3a59f1177cf108c9db96f0", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "ffaaaae2cd31e81101fe2c5fcb4b06ee26e7f2a90bec2d84454c91e38d37ca85", + "start_line": 1123, + "name": "datetime_module", + "arity": 1 + }, + "is_new_scope?/2:388": { + "line": 388, + "guard": null, + "pattern": "existing_scopes, bin_key", + "kind": "defp", + "end_line": 390, + "ast_sha": "cbe004c6bebca1787df8f88d4dfd3c318494a6ad968df77a5fe89ae9980d7624", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "5ca7f52fd09800e18736111685844ffb551dce6559177c33b20d3de994a9e61c", + "start_line": 388, + "name": "is_new_scope?", + "arity": 2 + }, + "router_scope/1:978": { + "line": 978, + "guard": null, + "pattern": "%Mix.Phoenix.Context{schema: schema} = context", + "kind": "defp", + "end_line": 984, + "ast_sha": "0d7fc0f2892e49997f1fd01ca54d2985de72520b87ad0a418762d749629cf57d", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "a10df912d236367b4ddac873fa63ed0935e8d382fc74d7f2263ec8b9f5f2018f", + "start_line": 978, + "name": "router_scope", + "arity": 1 + }, + "files_to_be_generated/1:478": { + "line": 478, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 601, + "ast_sha": "e5cac31341e58c35ce003e8b2a5aa04202c05741302e5844b6eb8f3eb1ada548", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "03e73ca95a75c1d2d78a9dde121b185af44f5852510091c17182762b6ed61c7a", + "start_line": 478, + "name": "files_to_be_generated", + "arity": 1 + }, + "maybe_inject_mix_dependency/2:671": { + "line": 671, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{mix_dependency: mix_dependency}", + "kind": "defp", + "end_line": 700, + "ast_sha": "bfea69ed6589347c31e537aa1cf1745263af39081038e1a43cde142d104d1949", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "216e4234777545924a22b369d849911dbb126111cc3c71c4af982fcdd36f8141", + "start_line": 671, + "name": "maybe_inject_mix_dependency", + "arity": 2 + }, + "inject_hashing_config/2:835": { + "line": 835, + "guard": null, + "pattern": "context, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", + "kind": "defp", + "end_line": 867, + "ast_sha": "d9dbbf759fd5e43c3d7bb06835606442e7fa0df292aa12f683a022547ea278dc", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "2ee79ffe5aec84d00c6d26463294e02456780f33e6ae25e5269acc318919a04a", + "start_line": 835, + "name": "inject_hashing_config", + "arity": 2 + }, + "inject_routes/3:660": { + "line": 660, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, paths, binding", + "kind": "defp", + "end_line": 668, + "ast_sha": "4172784d0a8152f0c66958a6be6272f80e4e64e3da9826af11f18facfa7a394e", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "59d6b1bccf03c14de79ea784700fe1481ea2e4a747aa0d3cf731930c55be0c20", + "start_line": 660, + "name": "inject_routes", + "arity": 3 + }, + "test_case_options/1:1120": { + "line": 1120, + "guard": "is_atom(adapter)", + "pattern": "adapter", + "kind": "defp", + "end_line": 1120, + "ast_sha": "41e6719b4a2e227d457699d30090fa21d3c461404f9dc5cb0aa07de529d33d9b", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "d3fee16e797b3237563e464208164395dd26fa533225d5f33d3ac14073cfff67", + "start_line": 1120, + "name": "test_case_options", + "arity": 1 + }, + "inject_tests/3:628": { + "line": 628, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", + "kind": "defp", + "end_line": 634, + "ast_sha": "32e1f0382bc89da5278950bbf731f9875eaabc35a3adf641a137e3a4806459da", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "6244102b2a8bf4aa2d86359c207b39406fed78aeb29be6173c03b1efb20a0076", + "start_line": 628, + "name": "inject_tests", + "arity": 3 + }, + "potential_layout_file_paths/1:827": { + "line": 827, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app}", + "kind": "defp", + "end_line": 831, + "ast_sha": "3c97c56b7a2645d2ac47ff7bb4bbcc73c6273c6a26591cacae9643571b97a4b0", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "6211b1f16a40c9628dc37fccb095093382ad58b96fe5b456fe8c29f5463cad71", + "start_line": 827, + "name": "potential_layout_file_paths", + "arity": 1 + }, + "raise_with_help/2:1089": { + "line": 1089, + "guard": null, + "pattern": "msg, :phx_generator_args", + "kind": "defp", + "end_line": 1091, + "ast_sha": "3020f6663792f64596cb9e1200a7276e8137994d20debe38addfc4dd789b3e23", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "9e68a0edc6684ad1f4504ccda38c68e82088944bb6be35ba9d10320c4db46c8d", + "start_line": 1089, + "name": "raise_with_help", + "arity": 2 + }, + "raise_with_help/2:1071": { + "line": 1071, + "guard": null, + "pattern": "msg, :general", + "kind": "defp", + "end_line": 1073, + "ast_sha": "cfbdbb965ba9e03b4489a2c7d52ec8a12048092fc12a95e6b824312b667c2a23", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "40dd554515ab7afa31e52625a35cce2370ead4347d80317a9665dae485639159", + "start_line": 1071, + "name": "raise_with_help", + "arity": 2 + }, + "maybe_inject_router_plug/2:750": { + "line": 750, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, binding", + "kind": "defp", + "end_line": 774, + "ast_sha": "a383ac647e02984cebff116525fa181219b9fc210be6e62bd10ffd42b47b4daa", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "1d7bf2aa758287aeee01b48ce0428279bd54fc8f42d63159dd076d5fbd2adf12", + "start_line": 750, + "name": "maybe_inject_router_plug", + "arity": 2 + }, + "maybe_inject_app_layout_menu/2:777": { + "line": 777, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding", + "kind": "defp", + "end_line": 818, + "ast_sha": "f3fcafa095bc56434f30b1e5a311e917922b771d724ae5c13bc7a14c42072441", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "cd93f22536f74ad959532a9822148f29fb84bf6072173bbdbd161867b60ef1ed", + "start_line": 777, + "name": "maybe_inject_app_layout_menu", + "arity": 2 + }, + "prompt_for_conflicts/1:428": { + "line": 428, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 433, + "ast_sha": "abeb352e91a7373299c3249c922a1fdb7ac8850e9cb3b44e0af90c2cd909acd9", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "231db0cdfeca98e4545e95eb50f349d470cf8ff282c4e1e43beb676a9c1be12b", + "start_line": 428, + "name": "prompt_for_conflicts", + "arity": 1 + }, + "test_case_options/1:1119": { + "line": 1119, + "guard": null, + "pattern": "Ecto.Adapters.Postgres", + "kind": "defp", + "end_line": 1119, + "ast_sha": "9182bc7d94fcba01e7385cd2ba2dbe426e0369b68efff2119f2aece41aa7526d", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "83e58942ef65c5baf9733d297f55ee811af0589ad32636f0bcd41ef91e772e88", + "start_line": 1119, + "name": "test_case_options", + "arity": 1 + }, + "inject_before_final_end/2:991": { + "line": 991, + "guard": null, + "pattern": "content_to_inject, file_path", + "kind": "defp", + "end_line": 1010, + "ast_sha": "4ebf59e80a43be391fcb6118c21f44174b4650772cc13280b2265474c4b9b737", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "b77de970d65b3fca8d0397a81f22a9f345fa662dccde7b6ed01a1a9c2cf0b8ef", + "start_line": 991, + "name": "inject_before_final_end", + "arity": 2 + }, + "print_injecting/2:1050": { + "line": 1050, + "guard": null, + "pattern": "file_path, suffix", + "kind": "defp", + "end_line": 1051, + "ast_sha": "6ef8e834a0d424143b6a345c4a33a6d761d2255ad8d7404de1d90b008302b2e5", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "e47e84d044af0ddc2d4070524c1ba32f4923889e065fe71ec3ebb496cfc2a7bb", + "start_line": 1050, + "name": "print_injecting", + "arity": 2 + }, + "raise_with_help/2:1104": { + "line": 1104, + "guard": null, + "pattern": "msg, :hashing_lib", + "kind": "defp", + "end_line": 1106, + "ast_sha": "98f4b197d84d3f74712d72031672e1d7329b40f3333ae0daa3ad1ea736e0ce50", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "8f2456b46b9890ca5fa59a37fabf7ac26eeca6cb288bf4a5093d8a66c422b621", + "start_line": 1104, + "name": "raise_with_help", + "arity": 2 + }, + "print_unable_to_read_file_error/2:1054": { + "line": 1054, + "guard": null, + "pattern": "file_path, help_text", + "kind": "defp", + "end_line": 1062, + "ast_sha": "a67071b500e520fb1f1bde0428e8ce696b55c210239a6450311b37947914ccca", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "329ae345b236f8b2a3acd6da08e108a67e01210c1b4d2557fdd9e123a5c7d914", + "start_line": 1054, + "name": "print_unable_to_read_file_error", + "arity": 2 + }, + "inject_context_functions/3:619": { + "line": 619, + "guard": null, + "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", + "kind": "defp", + "end_line": 625, + "ast_sha": "b820a725926f8ee740d0e816dafcff0dce6f8bc8ea9ce8d26788951c5a727529", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "3cfebdb6c536f3a28329f1645de10c04196323e78772d02e5f59f93f9e398475", + "start_line": 619, + "name": "inject_context_functions", + "arity": 3 + }, + "inject_scope_config/2:878": { + "line": 878, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding", + "kind": "defp", + "end_line": 911, + "ast_sha": "bc73bb670d2525a853155ca3d2b6a4372678d739015a0f83f414f34218b7767b", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "867494258afb20b0cd54f38e905807a0c3ac03308e5eba292a7c78a40c9a8c55", + "start_line": 878, + "name": "inject_scope_config", + "arity": 2 + }, + "print_shell_instructions/1:959": { + "line": 959, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 975, + "ast_sha": "2b17d2bf44a28b898052091d4c3b4e71f33471771725592ee0215fcbec1b90f3", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "7d1cf9e89dd6705e388e0f4ba2b63aaaa8fdb0310c87905f3ac4bcb833c200dd", + "start_line": 959, + "name": "print_shell_instructions", + "arity": 1 + }, + "maybe_inject_agents_md/3:914": { + "line": 914, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", + "kind": "defp", + "end_line": 956, + "ast_sha": "1db7b4d3fb34d453c2f86c87614b0882291c0a84f2b85365d7d06d66744fc74a", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "ab9915796ba1f6f68db74b2047c0d3da6a1a2d680fa838eaeea50f874f548b65", + "start_line": 914, + "name": "maybe_inject_agents_md", + "arity": 3 + }, + "default_hashing_library_option/0:328": { + "line": 328, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 331, + "ast_sha": "9179d2cfd8f33396b31efe78a75348215a3f87a8b14ce9af2f1b5a2d31070721", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "96407b6ed9df080fea251747edc6cf6ffb9d6741aaf47c7e9d0dd15007a86083", + "start_line": 328, + "name": "default_hashing_library_option", + "arity": 0 + }, + "datetime_module/1:1122": { + "line": 1122, + "guard": null, + "pattern": "%{timestamp_type: :naive_datetime}", + "kind": "defp", + "end_line": 1122, + "ast_sha": "69919f24a5d79b372b16a60da3a7ca3660453025025845dcee2ba8162b3c5aeb", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "da6eb9a92cc83e90f740d8d6ae31269ccfb60ee556d3edcecf18b010980c4295", + "start_line": 1122, + "name": "datetime_module", + "arity": 1 + }, + "maybe_inject_router_import/2:703": { + "line": 703, + "guard": null, + "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, binding", + "kind": "defp", + "end_line": 747, + "ast_sha": "2aa53abc3715dafe14a7a0ca60b39eee33bdbe22571e4ac1289690265ff5cfc8", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "301653b3f8878ac96a5cf9c4a6208119ef26e9dbd5e4e90f203dceed64803d85", + "start_line": 703, + "name": "maybe_inject_router_import", + "arity": 2 + }, + "inject_conn_case_helpers/3:650": { + "line": 650, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", + "kind": "defp", + "end_line": 657, + "ast_sha": "60a28f45743b05de6205b819020a453d414f51ae6e48ac7949849912b10fd661", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "aff6f7d4e233ba52b419c5a05ee7c124a949048929e1cb288f8dcfc950e4475c", + "start_line": 650, + "name": "inject_conn_case_helpers", + "arity": 3 + }, + "indent_spaces/2:1023": { + "line": 1023, + "guard": "is_binary(string) and is_integer(number_of_spaces)", + "pattern": "string, number_of_spaces", + "kind": "defp", + "end_line": 1029, + "ast_sha": "02b7e38afc642d2d491e80f9bc138020675600be4b4ee4992ab5fadeca03302c", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "e3718ff2396ab598a8e2e98d97c795101b6fcdeb357215e36eaaa4ad325dc831", + "start_line": 1023, + "name": "indent_spaces", + "arity": 2 + }, + "get_ecto_adapter!/1:1042": { + "line": 1042, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{repo: repo}", + "kind": "defp", + "end_line": 1046, + "ast_sha": "2857a865ef8b4f280163322e42db8c6bf93c59041f1d894268a5f027eb67afc6", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "7f02aa09415f3c4fb7b7584b8f9fbe1fdb595f9f389ad651c25b1aac62dbea87", + "start_line": 1042, + "name": "get_ecto_adapter!", + "arity": 1 + }, + "remap_files/1:605": { + "line": 605, + "guard": null, + "pattern": "files", + "kind": "defp", + "end_line": 606, + "ast_sha": "81e51bed68573fc09124ff69574449840d4095b398248d290cd0e28c42b2c665", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "d878e2c7ca4e95eba1223934545b2317e192841a186d236ca4e2d9439b3d3a39", + "start_line": 605, + "name": "remap_files", + "arity": 1 + }, + "generated_with_no_html?/0:293": { + "line": 293, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 301, + "ast_sha": "dea71c64fb54f9a0fe3e54697d9239c858fd68014c131817e072f4b244137209", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "5410d34b26908bd3a7709eac6dfe9b14b758cff498afc127059e27307bf285dd", + "start_line": 293, + "name": "generated_with_no_html?", + "arity": 0 + }, + "find_scope_name/2:360": { + "line": 360, + "guard": null, + "pattern": "context, existing_scopes", + "kind": "defp", + "end_line": 381, + "ast_sha": "bf5a3a39c03cb858a66d503bd1c5675c7e1480524f425c08b9600f148bcb8f76", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "e2769268ec41e9aba442a23db17136d54913e07353e06bb8d67d2e4ddd162a2e", + "start_line": 360, + "name": "find_scope_name", + "arity": 2 + }, + "web_path_prefix/1:988": { + "line": 988, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{web_path: nil}", + "kind": "defp", + "end_line": 988, + "ast_sha": "53ee3b94f81e0c1c9ea061599990930781627c1f3358667fcb64a633935b91d5", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "1e0d12dbfe606281f4d52aa45bf2eb7368de839cb4e09f9847dc43ef1b9df082", + "start_line": 988, + "name": "web_path_prefix", + "arity": 1 + }, + "datetime_now/1:1127": { + "line": 1127, + "guard": null, + "pattern": "%{timestamp_type: :utc_datetime}", + "kind": "defp", + "end_line": 1127, + "ast_sha": "ae9ee4fe31d93bfb5dd08a916c741ff26794417c98bf51195ddbbdef579403d2", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "7f46cfd7cc88a33763da4e7be3c02f1c18cbba85380b8983273c5b67d0bba06e", + "start_line": 1127, + "name": "datetime_now", + "arity": 1 + }, + "validate_required_dependencies!/0:266": { + "line": 266, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 289, + "ast_sha": "215f56979e5a9ffab5c5c717a6d9cfbc43c4edd21cc077536f55a58c5a0b93ef", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "d48c001a2f36a8da613fa20c108f4bd48b1bdd7a3b6941c1bdad39d7914f9f8c", + "start_line": 266, + "name": "validate_required_dependencies!", + "arity": 0 + }, + "print_injecting/1:1050": { + "line": 1050, + "guard": null, + "pattern": "x0", + "kind": "defp", + "end_line": 1050, + "ast_sha": "7b0a4446c2774727086335406acb0fba0e1ba5c9d97a32873b2b24d247817cbf", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "dd97eb4958e314405d344211a6db8df431e131d1890749f7da1c181fac1b474e", + "start_line": 1050, + "name": "print_injecting", + "arity": 1 + }, + "timestamp/0:1032": { + "line": 1032, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 1034, + "ast_sha": "f92225114515dfbf6f7bce4421d1ddd729c9aa3dabf028f410289210173cecdc", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "31815f67847bad4ae7aa82b79514b445b4ddd807b20356094669e72b46c33894", + "start_line": 1032, + "name": "timestamp", + "arity": 0 + }, + "copy_new_files/3:609": { + "line": 609, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", + "kind": "defp", + "end_line": 616, + "ast_sha": "fef5eb821ac1123c94bea2dc3a6db75b83131f50f805d1a3b90167b9bfc07621", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "e437877a206c52be2f064577f0b72865be75b6dc5258890e20a3863cfaf98385", + "start_line": 609, + "name": "copy_new_files", + "arity": 3 + }, + "run/1:174": { + "line": 174, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 174, + "ast_sha": "45d461968b8215bef2c6c061de66aed0ee82599bff15275e08028708db757d74", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "0525c212f181234f23d15f84712dae67cb2762f3bbb869470817c1a47a2a7962", + "start_line": 174, + "name": "run", + "arity": 1 + }, + "validate_args!/1:260": { + "line": 260, + "guard": null, + "pattern": "[_, _, _]", + "kind": "defp", + "end_line": 260, + "ast_sha": "1b56028c8938756c69633abc964cb1721b9b1668ddab2bfb2b50e8d0124b618e", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "16cf7b016db0f7cb3a20512823319f180dd1125b6c2c3d225c3dc0b1df1aed5c", + "start_line": 260, + "name": "validate_args!", + "arity": 1 + }, + "scope_config_string/4:411": { + "line": 411, + "guard": null, + "pattern": "context, key, default_scope, assign_key", + "kind": "defp", + "end_line": 423, + "ast_sha": "a77d656b01efb542247dfd9c7677841c829ea079c7c3eae0dc146bd4091e3b77", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "03f6cce830305196bdad40f6f452829dc7a4a702583620b19245738d64f2cac8", + "start_line": 411, + "name": "scope_config_string", + "arity": 4 + }, + "raise_with_help/1:1067": { + "line": 1067, + "guard": null, + "pattern": "msg", + "kind": "def", + "end_line": 1068, + "ast_sha": "b7cb2cf757347e02bac3da8bcbaee59b7b5e47d3bf8b31f68f28635bbff8b05f", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "5df5fd4354d460660b5e407826d2aa160af611f6f1175fb83fc96dffe9752c92", + "start_line": 1067, + "name": "raise_with_help", + "arity": 1 + }, + "put_live_option/1:1130": { + "line": 1130, + "guard": null, + "pattern": "schema", + "kind": "defp", + "end_line": 1150, + "ast_sha": "964b87401223e20ff5296b529c2e9bc6c019a54a9a0335b4bb2a9b4ff54ca9c9", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "69b3ba4a4111735f31a866af2915599769ffb64128ae006c537386bd238a60c4", + "start_line": 1130, + "name": "put_live_option", + "arity": 1 + }, + "datetime_module/1:1124": { + "line": 1124, + "guard": null, + "pattern": "%{timestamp_type: :utc_datetime_usec}", + "kind": "defp", + "end_line": 1124, + "ast_sha": "8e48feb00ef9d4da225d971648ecc0a8045a775871453849ebb7c5e9e3ccbf29", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "85bac05f0db2a217306fec2025b365dcb7977a5f4daf96a5e41f23752c9b7e88", + "start_line": 1124, + "name": "datetime_module", + "arity": 1 + }, + "datetime_now/1:1128": { + "line": 1128, + "guard": null, + "pattern": "%{timestamp_type: :utc_datetime_usec}", + "kind": "defp", + "end_line": 1128, + "ast_sha": "1a6d987cfea779ad40f2314b099d738ec8917d26b4f9f5f1bf469981d903c44c", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "108fa5ce6e67c83c841e9047c9922ae8a7d69e1ddb3b61161344d148b022258b", + "start_line": 1128, + "name": "datetime_now", + "arity": 1 + }, + "scope_config/3:335": { + "line": 335, + "guard": null, + "pattern": "context, requested_scope, assign_key", + "kind": "defp", + "end_line": 356, + "ast_sha": "04ce396601924f3d70dd7574fa8e1f48726218ccab12bf5ccd1818f6abeb8a3b", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "1e0122f932d2d0977393e4d5fcdc5efd5b6ff04fdc47113eca184e2bc37c6e0a", + "start_line": 335, + "name": "scope_config", + "arity": 3 + }, + "pad/1:1038": { + "line": 1038, + "guard": null, + "pattern": "i", + "kind": "defp", + "end_line": 1038, + "ast_sha": "a890a4d06d1c2099f5b0318876448a5612eaa099140679eb7ee14d2add5a7efa", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "019ee63a3ac952acdb672c9b9c381889dbecd8c4fea6d62ffa991c27316520a9", + "start_line": 1038, + "name": "pad", + "arity": 1 + }, + "get_layout_html_path/1:821": { + "line": 821, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 824, + "ast_sha": "699288801460547cf7bfcd7e146085c068f72cd3df946290ed62c4f96d581ccf", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "084a4e7de863bb6576596291902f4eacb1116e29c6c8bb021120f799f394e5d8", + "start_line": 821, + "name": "get_layout_html_path", + "arity": 1 + }, + "inject_context_test_fixtures/3:637": { + "line": 637, + "guard": null, + "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", + "kind": "defp", + "end_line": 647, + "ast_sha": "a56e9e6ed037b0ee3dc1d5d9fbcdc5e57dc4419e98b3f2c536c01ce42d2acbf3", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "72cde1ba57ef19b050af925ce5e5359bc3f35e9e2ee9df6554cdafd5fe501124", + "start_line": 637, + "name": "inject_context_test_fixtures", + "arity": 3 + }, + "prepend_newline/1:1040": { + "line": 1040, + "guard": "is_binary(string)", + "pattern": "string", + "kind": "defp", + "end_line": 1040, + "ast_sha": "694fcb60156c336cf8427ad250a356258b28e6212824dbdd46e55eacc1e1f44c", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "300ca99d53e6ffcf82085a37b235ffe2e4936386b623570bc8ca98c63ee606f9", + "start_line": 1040, + "name": "prepend_newline", + "arity": 1 + }, + "pad/1:1037": { + "line": 1037, + "guard": "i < 10", + "pattern": "i", + "kind": "defp", + "end_line": 1037, + "ast_sha": "5a8f6dba31e95ec6c137ce19a28fffb418b45cad50e7c7fe604c8a8406570326", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "b702f9d2b2eb412b80351a1db02d6367b03d9b917466520286d2f44bf08ef1dd", + "start_line": 1037, + "name": "pad", + "arity": 1 + }, + "new_scope/4:393": { + "line": 393, + "guard": null, + "pattern": "context, key, default_scope, assign_key", + "kind": "defp", + "end_line": 407, + "ast_sha": "c9ac8157a5914fef3b068b6100a2a975fff89f952ee34b7c5a1095fed0d2a454", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "bad773ef6ac7d5bc1b6588aefde26f8c272b3fac41cb4df4f912b7a442512b2b", + "start_line": 393, + "name": "new_scope", + "arity": 4 + }, + "web_path_prefix/1:989": { + "line": 989, + "guard": null, + "pattern": "%Mix.Phoenix.Schema{web_path: web_path}", + "kind": "defp", + "end_line": 989, + "ast_sha": "1a94b3321aaabc91c2d556d5b6d9943d9b0a24f2e2f64631f8e16a2e27140d59", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "5fd8ceef028de56bb6ab1c6e3b351fb8997177dd17886d0447c27f69b18c264b", + "start_line": 989, + "name": "web_path_prefix", + "arity": 1 + }, + "read_file/1:1016": { + "line": 1016, + "guard": null, + "pattern": "file_path", + "kind": "defp", + "end_line": 1019, + "ast_sha": "c82bd16318e344469d128f78331f2017591309c3843aea39f800e2c77551fd04", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "4e7401c080ff7dc56ec5fa35f7104985a5dac23d5f9c94868d676bc425bcffe3", + "start_line": 1016, + "name": "read_file", + "arity": 1 + }, + "web_app_name/1:254": { + "line": 254, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context", + "kind": "defp", + "end_line": 257, + "ast_sha": "c574b61ac11515305e348595f28331fd50b0b31d51844c73535a34bc56fd75fd", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "f130a0cf8a9e7d2e5042e77a57baf52119b0d59e9cd5c0930198927e66035295", + "start_line": 254, + "name": "web_app_name", + "arity": 1 + }, + "generated_with_no_assets_or_esbuild?/0:304": { + "line": 304, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 308, + "ast_sha": "07a0a731777f36cd53a4271a975f350e3a384bf99758c9483c56e971650334db", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "780e6109acef81d9c14dc39b7b339c52a19537074ce852a91e4cc1b73cf6c779", + "start_line": 304, + "name": "generated_with_no_assets_or_esbuild?", + "arity": 0 + }, + "validate_args!/1:262": { + "line": 262, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 263, + "ast_sha": "ea8e3213d2e54dd0152e93e9d31ecdc162de6b86b60c8a0edae5839f7ef68933", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "7a5cf251f3634c1231a3092f9e00d3b923d1f5fc99e2b03a24dd8feea51d298f", + "start_line": 262, + "name": "validate_args!", + "arity": 1 + }, + "maybe_inject_scope_config/2:870": { + "line": 870, + "guard": null, + "pattern": "%Mix.Phoenix.Context{} = context, binding", + "kind": "defp", + "end_line": 874, + "ast_sha": "f44d4b55f20ba1270fbef6c053601c03d4a9288beeabfcd3645edbc6710719e5", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "e2cd069889d02d01ef4f8178f99a3526688fc1420f836997d731391af0d7b0f4", + "start_line": 870, + "name": "maybe_inject_scope_config", + "arity": 2 + }, + "prompt_for_scope_conflicts/1:436": { + "line": 436, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 473, + "ast_sha": "71087d7ec6d66698f2c609354e098bdbc1c33b67679050421e53a46920b11395", + "source_file": "lib/mix/tasks/phx.gen.auth.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", + "source_sha": "bd3636aac24ab6435493098e9d35191198d2d42f0c051f36623a851a166b4327", + "start_line": 436, + "name": "prompt_for_scope_conflicts", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Auth.Injector": { + "app_layout_menu_code_to_inject/1:169": { + "line": 169, + "guard": null, + "pattern": "x0", + "kind": "def", + "end_line": 169, + "ast_sha": "ad56e90842058c640e06e88b10d90c9eed8a10b1ba03e0f83e77c61b87137ca7", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "9ed11f34e2931aede8d9e63e63a87548d7d728894f81675fa9557763ca3ca2c2", + "start_line": 169, + "name": "app_layout_menu_code_to_inject", + "arity": 1 + }, + "app_layout_menu_code_to_inject/2:169": { + "line": 169, + "guard": null, + "pattern": "x0, x1", + "kind": "def", + "end_line": 169, + "ast_sha": "78dff31dfabe16af5ad2a9972739c7f9b19847bfaccc90817456ebed80703fac", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "9ed11f34e2931aede8d9e63e63a87548d7d728894f81675fa9557763ca3ca2c2", + "start_line": 169, + "name": "app_layout_menu_code_to_inject", + "arity": 2 + }, + "app_layout_menu_code_to_inject/3:169": { + "line": 169, + "guard": null, + "pattern": "binding, padding, newline", + "kind": "def", + "end_line": 197, + "ast_sha": "ded110cef010fdfc38f11f4bed247a24e1ef90f09a4e730c2756e464a92e99bc", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "27fa4712fae262d2956e5119554651abd2a6d9a314f85d02df92abc5dc0d1ef1", + "start_line": 169, + "name": "app_layout_menu_code_to_inject", + "arity": 3 + }, + "app_layout_menu_help_text/2:156": { + "line": 156, + "guard": null, + "pattern": "file_path, binding", + "kind": "def", + "end_line": 162, + "ast_sha": "a2cf1ffd60566e47b9b7f1decd4dbf4da5bb6f1a123a990f14a5904ab355e67b", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "cdec6898ad330d0192754df2629348b06436ad4b302ebc4cea0fc08a10eee7c9", + "start_line": 156, + "name": "app_layout_menu_help_text", + "arity": 2 + }, + "app_layout_menu_inject/2:144": { + "line": 144, + "guard": null, + "pattern": "binding, template_str", + "kind": "def", + "end_line": 148, + "ast_sha": "1e9606ac71d2dbfeca2bec28458cfddf21ba7e0034576b9ce9b91f4bf36ceee3", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "a6ebaffff74be7028fd7c712d915e59a68f46a7f225776b377931fc7578dcfa8", + "start_line": 144, + "name": "app_layout_menu_inject", + "arity": 2 + }, + "app_layout_menu_inject_after_opening_body_tag/2:223": { + "line": 223, + "guard": null, + "pattern": "binding, file", + "kind": "defp", + "end_line": 237, + "ast_sha": "f45e2b2f629e4acfb33b169ecbfff118921793a240634797367794ed7cb5c36e", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "fdd8715feccf71ee3ac152647a0f383f955560418715e615b737db3fef47edff", + "start_line": 223, + "name": "app_layout_menu_inject_after_opening_body_tag", + "arity": 2 + }, + "app_layout_menu_inject_at_end_of_nav_tag/2:211": { + "line": 211, + "guard": null, + "pattern": "binding, file", + "kind": "defp", + "end_line": 219, + "ast_sha": "fc05fdbd4517daf9f3e2e9259d2e7853a6dbb0d966654257ab0ac06895b82c4a", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "71cd5ec4ab9606bc7f7db2c6f5c1a13ecf78f1e31f0155d8058cc04dd9fc4b9e", + "start_line": 211, + "name": "app_layout_menu_inject_at_end_of_nav_tag", + "arity": 2 + }, + "config_inject/2:44": { + "line": 44, + "guard": "is_binary(file) and is_binary(code_to_inject)", + "pattern": "file, code_to_inject", + "kind": "def", + "end_line": 54, + "ast_sha": "da803c617bab73917b93aef2e22b000d6e3f2a68c7d183da320d085db49f3ebb", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "2252639c24a3c58a50ce623b56286e81c351fbd97a623268204f839487dc18eb", + "start_line": 44, + "name": "config_inject", + "arity": 2 + }, + "do_mix_dependency_inject/2:23": { + "line": 23, + "guard": null, + "pattern": "mixfile, dependency", + "kind": "defp", + "end_line": 36, + "ast_sha": "fa78bc38fe429e7a88e00275f37a5a764a9789d1143374290efadf088d34c7f8", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "a0ef670a317d9d753d935769e680f5876cc0904e0db2692ce47538a797803419", + "start_line": 23, + "name": "do_mix_dependency_inject", + "arity": 2 + }, + "ensure_not_already_injected/2:283": { + "line": 283, + "guard": null, + "pattern": "file, inject", + "kind": "defp", + "end_line": 284, + "ast_sha": "ce28be63a0fcda30ce402ae8cd0abcc4413d96915b14695ac1a51f7f41fc6a33", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "e70c7c7c75de8aa12204467de69a9191160a23a627b9f39fac84cff8c7fb4b08", + "start_line": 283, + "name": "ensure_not_already_injected", + "arity": 2 + }, + "formatting_info/2:200": { + "line": 200, + "guard": null, + "pattern": "template, tag", + "kind": "defp", + "end_line": 208, + "ast_sha": "e1454f89976b09b407581ad580639f9e77942c8f69b143437eb4dce71f080c6f", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "b8cabed576281458b7121c945b78bc21343cf8f8895d739067bfa676c8e48a1c", + "start_line": 200, + "name": "formatting_info", + "arity": 2 + }, + "get_line_ending/1:305": { + "line": 305, + "guard": null, + "pattern": "file", + "kind": "defp", + "end_line": 308, + "ast_sha": "c8d78e0df286185b62f59c3741a0e136cd0c840483308f4f57282513d061a57e", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "593ad4a6b643eec7152e1de820ec0c6798ba1bbb959017b7652760f95975198b", + "start_line": 305, + "name": "get_line_ending", + "arity": 1 + }, + "indent_spaces/2:312": { + "line": 312, + "guard": null, + "pattern": "x0, x1", + "kind": "defp", + "end_line": 312, + "ast_sha": "dbbe4566298fd1bf5b43b3e9f518ffc0978376df1e51b3bec1d971a693c168e6", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "2954e8656d3f7816922b162ba40ab240cc2d5fbfa258abeef93c690d702bff59", + "start_line": 312, + "name": "indent_spaces", + "arity": 2 + }, + "indent_spaces/3:312": { + "line": 312, + "guard": "is_binary(string) and is_integer(number_of_spaces)", + "pattern": "string, number_of_spaces, newline", + "kind": "defp", + "end_line": 318, + "ast_sha": "ffe50878da165fdfa2a76274aa6bc36348d5a95f24ab29b7116c2b606128ad8a", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "1dd240ef8d51348305742dba2a26329ee603ee2a5b8732a8ee5c8f076b21da6c", + "start_line": 312, + "name": "indent_spaces", + "arity": 3 + }, + "inject_before_final_end/2:266": { + "line": 266, + "guard": "is_binary(code) and is_binary(code_to_inject)", + "pattern": "code, code_to_inject", + "kind": "def", + "end_line": 278, + "ast_sha": "4e9119ab1976b162ee90d94557244edc7200182a177bef2a8f16f75ec8817c49", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "5b5c989bf04b2eaa81591118f73e796f1b971be924233813103e20f4c7180cb8", + "start_line": 266, + "name": "inject_before_final_end", + "arity": 2 + }, + "inject_unless_contains/3:244": { + "line": 244, + "guard": null, + "pattern": "code, dup_check, inject_fn", + "kind": "def", + "end_line": 245, + "ast_sha": "4cf3ba333b128433fd0b77ba03d1aed1c1acbb27b2cf5495df7784055b7f191f", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "a80b2e88113f15b67ddb5afa1b1c0afa84a72db1a9296ea94039f63cdd71d1e7", + "start_line": 244, + "name": "inject_unless_contains", + "arity": 3 + }, + "inject_unless_contains/4:248": { + "line": 248, + "guard": "is_binary(code) and is_binary(code_to_inject) and is_binary(dup_check) and\n is_function(inject_fn, 2)", + "pattern": "code, dup_check, code_to_inject, inject_fn", + "kind": "def", + "end_line": 255, + "ast_sha": "b750cb9d257368ca9ece94aa1c1b4cfb8385e10147922c74dc47cafdfd16a415", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "52ecaccf006ebb903f9f58a0c73fdbf891feae986aadcae1a1ee7d4ca736001f", + "start_line": 248, + "name": "inject_unless_contains", + "arity": 4 + }, + "mix_dependency_inject/2:14": { + "line": 14, + "guard": null, + "pattern": "mixfile, dependency", + "kind": "def", + "end_line": 17, + "ast_sha": "a230f3fccefd744a21a417521bec74c8d93cdb9f9464730507e77cb28ff78cf2", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "1ad7e915e97253561e1c6be84ae3208b99eea32d51e6023d76e1d0487cdfbd55", + "start_line": 14, + "name": "mix_dependency_inject", + "arity": 2 + }, + "normalize_line_endings_to_file/2:300": { + "line": 300, + "guard": null, + "pattern": "code, file", + "kind": "defp", + "end_line": 301, + "ast_sha": "2c4b70756190c3d1c3ac11703f8ded92077519d8c42e88b5e7a1ce3b6b6df5d7", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "ca50b9b5f2c32f0303fd9d9ca116329672d78a07bb26000a0d05f9a5e5dddbb8", + "start_line": 300, + "name": "normalize_line_endings_to_file", + "arity": 2 + }, + "router_plug_code/1:133": { + "line": 133, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 134, + "ast_sha": "a0feded73cab800b3ce5f5f6be1c174c5fd4b186335bdede455eb94bf29c6415", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "0eaf0c486f5e52e5d8001cec2e22dda7eeec569196e9bbf3196471bdb5763ab1", + "start_line": 133, + "name": "router_plug_code", + "arity": 1 + }, + "router_plug_help_text/2:121": { + "line": 121, + "guard": null, + "pattern": "file_path, binding", + "kind": "def", + "end_line": 128, + "ast_sha": "0624feb7ab1f450dfc540f3af9e3141efbd1cbcdf958ff194f135792a8319542", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "86ded1f1e178839d95f7c2cbabeaae001cf8a1956d604a983540f473bf22013c", + "start_line": 121, + "name": "router_plug_help_text", + "arity": 2 + }, + "router_plug_inject/2:100": { + "line": 100, + "guard": "is_binary(file)", + "pattern": "file, binding", + "kind": "def", + "end_line": 111, + "ast_sha": "49b4479dd68fedc56a2a2237e30a0650fe4c7b0b347cc3773c335247dfd895e1", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "e09fc1621d18bd99ebc46985d6c457925ad5956ecdf086ce0662d5743a4d680d", + "start_line": 100, + "name": "router_plug_inject", + "arity": 2 + }, + "router_plug_name/1:137": { + "line": 137, + "guard": null, + "pattern": "binding", + "kind": "defp", + "end_line": 138, + "ast_sha": "4b6f4e014a4e1f3ce4b1a2c36dbdc9565db7bc50d2e4e416c3789b9eb97b2608", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "fc18e3e0a15c3a9690eab9b6c9c56472d8a7601462aac44642f0f3a3a0981d9a", + "start_line": 137, + "name": "router_plug_name", + "arity": 1 + }, + "split_with_self/2:292": { + "line": 292, + "guard": null, + "pattern": "contents, text", + "kind": "defp", + "end_line": 295, + "ast_sha": "3141c1636c63d8b665130e69a25e7ae3bf13a5c5f180d4e43b513d62de540bb5", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "29fb79d2a2386fbe171d94503bd3c5702c6ebed39be0c55476c3dad22fd44bf7", + "start_line": 292, + "name": "split_with_self", + "arity": 2 + }, + "test_config_code/1:86": { + "line": 86, + "guard": null, + "pattern": "%Mix.Tasks.Phx.Gen.Auth.HashingLibrary{test_config: test_config}", + "kind": "defp", + "end_line": 89, + "ast_sha": "d5bff2421c0aea67bac65427e798253074cdad7989e81b7bef23c11c4eaf4a0d", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "2318fd8f04c58f32ec9753ace7949440af049c86b1ea77203202952587b05007", + "start_line": 86, + "name": "test_config_code", + "arity": 1 + }, + "test_config_help_text/2:78": { + "line": 78, + "guard": null, + "pattern": "file_path, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", + "kind": "def", + "end_line": 82, + "ast_sha": "c5d70d02cabdbd429bbb7c060bb6398b6a96d61142dcdb7c898619e44c35ca42", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "e2cb79ec6ac7e7d6199776bc16463db84a9ae7571d5a898c04f43575ba8d4353", + "start_line": 78, + "name": "test_config_help_text", + "arity": 2 + }, + "test_config_inject/2:65": { + "line": 65, + "guard": "is_binary(file)", + "pattern": "file, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", + "kind": "def", + "end_line": 71, + "ast_sha": "901651af7cdc1e371caef478bb52bf15d2d2e39b21fcb28cada0c23b41c4ce74", + "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", + "source_sha": "c72c42245f3de9bcf290f3e6767cd8cd7d90ec396410c927a3a9b947032d4747", + "start_line": 65, + "name": "test_config_inject", + "arity": 2 + } + }, + "Mix.Tasks.Phx": { + "general/0:32": { + "line": 32, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 38, + "ast_sha": "3050070af5a1364e13c0150b65c334bf963a313adbca59d547a8d59e500ba05e", + "source_file": "lib/mix/tasks/phx.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", + "source_sha": "b0e1d22add9d555918e449af9dae3768f1e18eace30d3bff167b73b8a05fdd44", + "start_line": 32, + "name": "general", + "arity": 0 + }, + "run/1:21": { + "line": 21, + "guard": "=:=(version, \"-v\") or =:=(version, \"--version\")", + "pattern": "[version]", + "kind": "def", + "end_line": 22, + "ast_sha": "027b701f2c254592bca06521c00af7f6651026d61451b28fe958a1c243bb2730", + "source_file": "lib/mix/tasks/phx.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", + "source_sha": "d3a22d33b7729da940a6b0253d6d17c283dbe56b02d78dddf4f405800b05a652", + "start_line": 21, + "name": "run", + "arity": 1 + }, + "run/1:25": { + "line": 25, + "guard": null, + "pattern": "args", + "kind": "def", + "end_line": 28, + "ast_sha": "96c16fc40ec19ed7ebbf484e08b5bc7cecd51c1d0d4bd281086e1e81e3d1a8d6", + "source_file": "lib/mix/tasks/phx.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", + "source_sha": "e5b9618eb03792eaa310e3081b48b36039ae6ad03ff3aea26b54e676c337de7e", + "start_line": 25, + "name": "run", + "arity": 1 + } + }, + "Phoenix.Router.Resource": { + "__struct__/0:24": { + "line": 24, + "guard": null, + "pattern": "", + "kind": "def", + "end_line": 24, + "ast_sha": "3ddf9201601595adc9c5382b6b96cb6fe37c9516c3f2c6086b2cbc40122cbb76", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "4acb922e7c1776213c3cb445b245cb41a12e0d007664de3dde5d31f8dc5878fa", + "start_line": 24, + "name": "__struct__", + "arity": 0 + }, + "__struct__/1:24": { + "line": 24, + "guard": null, + "pattern": "kv", + "kind": "def", + "end_line": 24, + "ast_sha": "4b1f9c53dcab7f9debd09f66c76b081723e0a4965841daadfe33d70450747076", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "4acb922e7c1776213c3cb445b245cb41a12e0d007664de3dde5d31f8dc5878fa", + "start_line": 24, + "name": "__struct__", + "arity": 1 + }, + "build/3:30": { + "line": 30, + "guard": "is_atom(controller) and is_list(options)", + "pattern": "path, controller, options", + "kind": "def", + "end_line": 48, + "ast_sha": "7fe608085a0b7bd90c0fc670c11a2d3fc50195fec42747a6b7d8a15c6186d172", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "b3f3ad3044a512f07353a67ab30f449ab8427bb284b40ad87ef1398488a0b256", + "start_line": 30, + "name": "build", + "arity": 3 + }, + "default_actions/1:84": { + "line": 84, + "guard": null, + "pattern": "true = _singleton", + "kind": "defp", + "end_line": 84, + "ast_sha": "e155983070e2569b4e303fada5cff1c587a6eaa12201c0fc21e47d0b04fe7f79", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "1936fdc53d44a6f7427be4689c69c57f7d58fcea86ad9971012874078bd5e173", + "start_line": 84, + "name": "default_actions", + "arity": 1 + }, + "default_actions/1:85": { + "line": 85, + "guard": null, + "pattern": "false = _singleton", + "kind": "defp", + "end_line": 85, + "ast_sha": "9db9839a268d7a735cd8a68d193f10bf8306b51cd8de24f49983a1311757da7b", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "fcca3764db6546033df3806297e766e0d9831eb3eeedd51375bc26e498d7bbee", + "start_line": 85, + "name": "default_actions", + "arity": 1 + }, + "extract_actions/2:51": { + "line": 51, + "guard": null, + "pattern": "opts, singleton", + "kind": "defp", + "end_line": 64, + "ast_sha": "ab48fb60d8137258856f6b2d72c384ae07fd1d9bd455a3174cc7f41a04b79557", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "d4d01282a50fc1e65478bc10d859ba4d02ff1f9236802b7db72b387d9be4dea5", + "start_line": 51, + "name": "extract_actions", + "arity": 2 + }, + "validate_actions/3:68": { + "line": 68, + "guard": null, + "pattern": "type, singleton, actions", + "kind": "defp", + "end_line": 81, + "ast_sha": "af46cfe7794910fb10bdb9c17877ec52c1580876ee39028412806e9e618b210d", + "source_file": "lib/phoenix/router/resource.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", + "source_sha": "23bfd893d56fc6fd89140491e3bd34e84f9bdd7fb7872bcd0cfc9584f900cfae", + "start_line": 68, + "name": "validate_actions", + "arity": 3 + } + }, + "Mix.Tasks.Phx.Gen.Cert": { + "basic_constraints/0:204": { + "line": 204, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 204, + "ast_sha": "0e681c5f76ea7716ee05cc37312eb06916b2035387308fa4c27ad1607a14f972", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 204, + "name": "basic_constraints", + "arity": 0 + }, + "basic_constraints/2:204": { + "line": 204, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 204, + "ast_sha": "afebfff5873c271f9c083ff0fbd7e9a31cf4c7107048f627b3026f396d7a2d1b", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 204, + "name": "basic_constraints", + "arity": 2 + }, + "rsa_public_key/0:148": { + "line": 148, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 148, + "ast_sha": "ba1337896a45e0cc9f1b1bc8606d6e32f3789c720c6bd721d8293747a13ce3e9", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 148, + "name": "rsa_public_key", + "arity": 0 + }, + "validity/2:180": { + "line": 180, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 180, + "ast_sha": "0be112fc7c8f43d8a5a52a0f18ee7f755c6dce47fcd922bdf4e2b3341c41aa78", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 180, + "name": "validity", + "arity": 2 + }, + "certificate_and_key/3:89": { + "line": 89, + "guard": null, + "pattern": "key_size, name, hostnames", + "kind": "def", + "end_line": 112, + "ast_sha": "c5e5afa09f7cce0eb249e0d31458ab02a275d894b91ce5912fc53d8650aea50d", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "61be263fb1fd329dafd03051a8f9445f895a2b6a5208234acb8148a1cb4bcdc4", + "start_line": 89, + "name": "certificate_and_key", + "arity": 3 + }, + "otp_subject_public_key_info/1:186": { + "line": 186, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 186, + "ast_sha": "fa1600c0e011f556ee1a52849fc5649c636e7162e391279e256b66e50bd97e64", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 186, + "name": "otp_subject_public_key_info", + "arity": 1 + }, + "otp_tbs_certificate/1:168": { + "line": 168, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 168, + "ast_sha": "ddcb3437b28d0297f2d657643667ee9c04c30ae8ac1c2c27b9b3c3e168d56bdb", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 168, + "name": "otp_tbs_certificate", + "arity": 1 + }, + "key_identifier/1:306": { + "line": 306, + "guard": null, + "pattern": "public_key", + "kind": "defp", + "end_line": 307, + "ast_sha": "010dff7eeb82e0080cd0acdda8e451d3e2ae12363eda168350d07c814ce9e119", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "d22d93c3bbe121892419a94944a342125909d67356dd006fc275705ace46a83a", + "start_line": 306, + "name": "key_identifier", + "arity": 1 + }, + "extract_public_key/1:162": { + "line": 162, + "guard": null, + "pattern": "{:RSAPrivateKey, _, m, e, _, _, _, _, _, _, _}", + "kind": "defp", + "end_line": 163, + "ast_sha": "62f6e580c26fde55069992dc796eb8a6d1b6525ab48ab0508979b5bea77404c0", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "2e741bffc189dd0fd3db7f585a6a54fcfd5332bbee6e5e6d89611be5302f941d", + "start_line": 162, + "name": "extract_public_key", + "arity": 1 + }, + "generate_rsa_key/2:154": { + "line": 154, + "guard": null, + "pattern": "keysize, e", + "kind": "defp", + "end_line": 158, + "ast_sha": "37c104b29040b16e0760fbe9132c715cd5b3609d317d1046d19010e52ae422c4", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "276c9910cd9306d31978c64c19aba8cc2f6a750b736d976f7e386df272c71b90", + "start_line": 154, + "name": "generate_rsa_key", + "arity": 2 + }, + "otp_subject_public_key_info/0:186": { + "line": 186, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 186, + "ast_sha": "17aaba81a3ace80415638f73469812c98bcf4b0cf1fc8d4ca3762c6092c0ebf6", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 186, + "name": "otp_subject_public_key_info", + "arity": 0 + }, + "basic_constraints/1:204": { + "line": 204, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 204, + "ast_sha": "e35f671b29b21ca8b8936d3165c0dbc24aba9ad0139eeceffcd7aa6869a90143", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 204, + "name": "basic_constraints", + "arity": 1 + }, + "otp_subject_public_key_info/2:186": { + "line": 186, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 186, + "ast_sha": "30f7303f1b82b94408253158c8024054209ebda1d89af40db19997c35e5f39a8", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 186, + "name": "otp_subject_public_key_info", + "arity": 2 + }, + "rsa_private_key/1:142": { + "line": 142, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 142, + "ast_sha": "38e82ed04d99a260c0a6a53b7f5e7aeea7394b0404f2b92672ca8f8500fbea70", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 142, + "name": "rsa_private_key", + "arity": 1 + }, + "extensions/2:276": { + "line": 276, + "guard": null, + "pattern": "public_key, hostnames", + "kind": "defp", + "end_line": 301, + "ast_sha": "ea4aeaed45b7923570f88b9ef9ce060a67480bdabc14210bd2dadcd4ceeee84e", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "31e79ba3a3d28ea17ba9e1026f8bde8de68fe6513cd1257f527fa545da29aec6", + "start_line": 276, + "name": "extensions", + "arity": 2 + }, + "run/1:47": { + "line": 47, + "guard": null, + "pattern": "all_args", + "kind": "def", + "end_line": 85, + "ast_sha": "643f2603b375c3a3f1cb90b8e1c62155d7a465f3332c7a17b91ee3aafbb320b8", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "e85bcaec49d8f3c522412772dbc7d9937a4f4594cd1c755b1094f66ac8e1748d", + "start_line": 47, + "name": "run", + "arity": 1 + }, + "public_key_algorithm/2:192": { + "line": 192, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 192, + "ast_sha": "bbaa200c4323e0c9ed708ce49bc37af567df1589cc26a8577595b23b49ac1bc1", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 192, + "name": "public_key_algorithm", + "arity": 2 + }, + "signature_algorithm/1:174": { + "line": 174, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 174, + "ast_sha": "de6ab0e51d7462030c7f86d32ccc47c41f3d5ae822a20ce85bb6932964410c5a", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 174, + "name": "signature_algorithm", + "arity": 1 + }, + "otp_tbs_certificate/0:168": { + "line": 168, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 168, + "ast_sha": "73895694168a0d9fee58eb586be5f8ae8d6a3a51f64c79f3015b6e05425be967", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 168, + "name": "otp_tbs_certificate", + "arity": 0 + }, + "new_cert/3:232": { + "line": 232, + "guard": null, + "pattern": "public_key, common_name, hostnames", + "kind": "defp", + "end_line": 264, + "ast_sha": "d3173971e37eda060104e0a236e315d1700e5bc43a44266be19ee2568866e16b", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "1cb5f21dfa5b6cd7afce71b3433872431564de873e18f1d0b5c4debf1e43ceb8", + "start_line": 232, + "name": "new_cert", + "arity": 3 + }, + "extension/2:198": { + "line": 198, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 198, + "ast_sha": "0fbcfcc76b57a45d3e6efd9960c10271e3fa2cf6b5595facce1d0908f5fd4597", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 198, + "name": "extension", + "arity": 2 + }, + "rdn/1:268": { + "line": 268, + "guard": null, + "pattern": "common_name", + "kind": "defp", + "end_line": 272, + "ast_sha": "a7073dd3f3743af67d11cc80afca00f100b49901909b4d2fda4ffb9c8256ead3", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "568717d5125a101f2a46ac1c4993824bc44366f64c787a2c1932471b9fd8cf5c", + "start_line": 268, + "name": "rdn", + "arity": 1 + }, + "public_key_algorithm/1:192": { + "line": 192, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 192, + "ast_sha": "eb7dca39114d26e46500b59a929b86ed27de738edfa69ecabc97de93352d8a01", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 192, + "name": "public_key_algorithm", + "arity": 1 + }, + "rsa_private_key/0:142": { + "line": 142, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 142, + "ast_sha": "500965ae58c255135fb78c62cf008d9797954ed6c95e77753d8769cd2851a2f0", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 142, + "name": "rsa_private_key", + "arity": 0 + }, + "otp_tbs_certificate/2:168": { + "line": 168, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 168, + "ast_sha": "df88a26d037db383a1c36b3987b7690f19091f114fee687ab0635d6e2c4fc582", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 168, + "name": "otp_tbs_certificate", + "arity": 2 + }, + "attr/0:210": { + "line": 210, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 210, + "ast_sha": "625230d22c289c5aa1383fdaa579c581729fa5e133ecae632cd393a2c43a6499", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 210, + "name": "attr", + "arity": 0 + }, + "public_key_algorithm/0:192": { + "line": 192, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 192, + "ast_sha": "228109cd362d755c0a50f72ce05b4d61a995d115b21f007f1cecf87dbd7c0c0b", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 192, + "name": "public_key_algorithm", + "arity": 0 + }, + "rsa_private_key/2:142": { + "line": 142, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 142, + "ast_sha": "3edbc0033af63843611154e902709454cfa119e7093f2c13cbf4d7cf9f675983", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 142, + "name": "rsa_private_key", + "arity": 2 + }, + "extension/0:198": { + "line": 198, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 198, + "ast_sha": "5f5393831ff7a6476dc4ea7a13906726d350734b92a5ae0076ed25bad36bbb32", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 198, + "name": "extension", + "arity": 0 + }, + "signature_algorithm/0:174": { + "line": 174, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 174, + "ast_sha": "73d7a989e803f0837fea886b4208eeff7f65f3fcb2e0caafeef7e7d4bcc4b18d", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 174, + "name": "signature_algorithm", + "arity": 0 + }, + "rsa_public_key/2:148": { + "line": 148, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 148, + "ast_sha": "f323a2417ecbba07797688a77b48521161380f9640247d363c503789a2e882fe", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 148, + "name": "rsa_public_key", + "arity": 2 + }, + "print_shell_instructions/2:115": { + "line": 115, + "guard": null, + "pattern": "keyfile, certfile", + "kind": "defp", + "end_line": 134, + "ast_sha": "6b4bcd0cb3eb21d39e0f32c64412a35325bc656904fcca46b1e6fadfb8d3eaf1", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "92f856175238411994c4da6817139742e90a1214f7e96d906a32fc4dcc3677aa", + "start_line": 115, + "name": "print_shell_instructions", + "arity": 2 + }, + "extension/1:198": { + "line": 198, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 198, + "ast_sha": "3f008778390d565523fea784ae4defa3be2f22b55090b4d8ffcc2ecdd959cea3", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 198, + "name": "extension", + "arity": 1 + }, + "validity/1:180": { + "line": 180, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 180, + "ast_sha": "d60be99887e0144b243c122e026d4db48f74ac2f14a6337bbf249fd508fb5d28", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 180, + "name": "validity", + "arity": 1 + }, + "validity/0:180": { + "line": 180, + "guard": null, + "pattern": "", + "kind": "defmacrop", + "end_line": 180, + "ast_sha": "4f8a8a6d27025844b936da3ee67721542bc7fe371c731ac8a135caa4c36187e4", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 180, + "name": "validity", + "arity": 0 + }, + "rsa_public_key/1:148": { + "line": 148, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 148, + "ast_sha": "6a795dfc40ee1ece67316a96e3cb1ba63ed56059b0dfcbe86db0887c48966d7b", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 148, + "name": "rsa_public_key", + "arity": 1 + }, + "attr/1:210": { + "line": 210, + "guard": null, + "pattern": "args", + "kind": "defmacrop", + "end_line": 210, + "ast_sha": "8d72c41dd33c05326e2374fa9f2b20bb35bd5e349a780d4fe633558e32e9b251", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 210, + "name": "attr", + "arity": 1 + }, + "attr/2:210": { + "line": 210, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 210, + "ast_sha": "c266007d671940dd394527b8f8d665ffb291ba7526f0dae322f2fec0b2993afb", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 210, + "name": "attr", + "arity": 2 + }, + "signature_algorithm/2:174": { + "line": 174, + "guard": null, + "pattern": "record, args", + "kind": "defmacrop", + "end_line": 174, + "ast_sha": "0c80c94bf2d7bb596cd2cc553810da1510e668f4f61aec139f53818527505ca5", + "source_file": "lib/mix/tasks/phx.gen.cert.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", + "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", + "start_line": 174, + "name": "signature_algorithm", + "arity": 2 + } + }, + "Mix.Tasks.Phx.Gen.Auth.Migration": { + "build/1:6": { + "line": 6, + "guard": "is_atom(ecto_adapter)", + "pattern": "ecto_adapter", + "kind": "def", + "end_line": 10, + "ast_sha": "cec9dcf8ae7824ea58b7ebac4759c88e30181fe3313d7ad58de4be701b9d56a3", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "32fc3f86439149c0030698a01854f419ddfafd4cfe27941a5dcea665dbbf839c", + "start_line": 6, + "name": "build", + "arity": 1 + }, + "column_definition/2:26": { + "line": 26, + "guard": null, + "pattern": ":email, Ecto.Adapters.Postgres", + "kind": "defp", + "end_line": 26, + "ast_sha": "8a5c262d3e0d66ed3da62d0f3b03fe3e4eeed107ee1055791c97aa75d4b50b6e", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "7710259ae2884c5cd67fed5e75e4383fe7775432446cb6cc2ef3b74b4d9e8f43", + "start_line": 26, + "name": "column_definition", + "arity": 2 + }, + "column_definition/2:27": { + "line": 27, + "guard": null, + "pattern": ":email, Ecto.Adapters.SQLite3", + "kind": "defp", + "end_line": 27, + "ast_sha": "2b2b4ba617e07e0127679364205f2bca5fda542857b2e1e8d6c7e431a0860a98", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "d76e5bdc06cc12c246e5e0bf5a442ca55837b3ac6fe063d1f987cd3d786e4e2b", + "start_line": 27, + "name": "column_definition", + "arity": 2 + }, + "column_definition/2:28": { + "line": 28, + "guard": null, + "pattern": ":email, _", + "kind": "defp", + "end_line": 28, + "ast_sha": "db12d52853ef14fd7a7946cfa8d0238896aacde28221325a3c85d859b73014fe", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "6c1484d6bde44bfd3a8510d4ab57137813b9577ae4382f25b2c05e52c3f75355", + "start_line": 28, + "name": "column_definition", + "arity": 2 + }, + "column_definition/2:30": { + "line": 30, + "guard": null, + "pattern": ":token, Ecto.Adapters.Postgres", + "kind": "defp", + "end_line": 30, + "ast_sha": "0ca658a6040b6c3f6585a6ac6a5057e3ba8198e9afc40cd38a31301a9e5d1264", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "b15d5b4491d4bc08efef9cbd9e21b1a3fc0d9c402acd747c24d09ae03831c240", + "start_line": 30, + "name": "column_definition", + "arity": 2 + }, + "column_definition/2:32": { + "line": 32, + "guard": null, + "pattern": ":token, _", + "kind": "defp", + "end_line": 32, + "ast_sha": "9efd730eccff08203aec7707c4240dad86872a866a9aad459d942a9bee3f1ebf", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "b067d21e5256ee508b8f9f48f0f72bbdae7977e3d9aed4067d92b5b2daca135a", + "start_line": 32, + "name": "column_definition", + "arity": 2 + }, + "column_definitions/1:20": { + "line": 20, + "guard": null, + "pattern": "ecto_adapter", + "kind": "defp", + "end_line": 23, + "ast_sha": "ccee25ebc00c54e7e9058d4240b6b9e496c910175780f8bffd981d3b5283abe7", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "1a8097771411acc16cedd840b0fe82f8f790e68f7e5de49aa7f5ec428e559c67", + "start_line": 20, + "name": "column_definitions", + "arity": 1 + }, + "extensions/1:14": { + "line": 14, + "guard": null, + "pattern": "Ecto.Adapters.Postgres", + "kind": "defp", + "end_line": 14, + "ast_sha": "81b4cabe530f0b5287c97fc7e73770176087b23f2f54b354421e3d04e9e138e1", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "72e4d89dc89a89f2287bbbde75f644820c65a8b628f194f5393fd8441433376d", + "start_line": 14, + "name": "extensions", + "arity": 1 + }, + "extensions/1:18": { + "line": 18, + "guard": null, + "pattern": "_", + "kind": "defp", + "end_line": 18, + "ast_sha": "cd9a1ecf3037be6bf542dbbbf970b1538abea2533a8a8759803a3870342601ce", + "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", + "source_sha": "e721aac73af1bba172ba4cd86bddde34d2c9a8344857f3f8c9ecc4aea3139d0b", + "start_line": 18, + "name": "extensions", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Gen.Presence": { + "paths/0:66": { + "line": 66, + "guard": null, + "pattern": "", + "kind": "defp", + "end_line": 66, + "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", + "source_file": "lib/mix/tasks/phx.gen.presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", + "start_line": 66, + "name": "paths", + "arity": 0 + }, + "run/1:19": { + "line": 19, + "guard": null, + "pattern": "[]", + "kind": "def", + "end_line": 20, + "ast_sha": "c1f727852ef6d0e1f908a1361b772ce15f70de5a4dc4358097f461f5cb280139", + "source_file": "lib/mix/tasks/phx.gen.presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "source_sha": "d8e2875d64949f609af7e416af492920048c9431328297452734754d74e5fc54", + "start_line": 19, + "name": "run", + "arity": 1 + }, + "run/1:23": { + "line": 23, + "guard": null, + "pattern": "[alias_name]", + "kind": "def", + "end_line": 58, + "ast_sha": "ff0fdec2fd73ccde273823c19183029d2a4bbf2143e69d79c6e38352fb937416", + "source_file": "lib/mix/tasks/phx.gen.presence.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", + "source_sha": "d607e4fe106896a27c0e93886ae8d9cd89f3e09a366f2e5cf8ebf125ff40b308", + "start_line": 23, + "name": "run", + "arity": 1 + } + }, + "Mix.Tasks.Phx.Digest.Clean": { + "run/1:43": { + "line": 43, + "guard": null, + "pattern": "all_args", + "kind": "def", + "end_line": 73, + "ast_sha": "f54e6551186ad42c4d8835d77c9a54a964e198253fac6e56818180da680a9baf", + "source_file": "lib/mix/tasks/phx.digest.clean.ex", + "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", + "source_sha": "cce93f3b4b0920f70c578b4f7e84e42bc805dec5085b8be4121c2985204515a2", + "start_line": 43, + "name": "run", + "arity": 1 + } + } + }, + "types": { + "Phoenix.Logger": [], + "Mix.Tasks.Phx.Gen.Notifier": [], + "Phoenix.Channel": [ + { + "line": 341, + "name": "socket_ref", + "params": [], + "kind": "type", + "definition": "@type socket_ref() :: {Pid, module(), binary(), binary(), binary()}" + }, + { + "line": 340, + "name": "reply", + "params": [], + "kind": "type", + "definition": "@type reply() :: atom() | {atom(), payload()}" + }, + { + "line": 339, + "name": "payload", + "params": [], + "kind": "type", + "definition": "@type payload() :: map() | term() | {:binary, binary()}" + } + ], + "Phoenix.Channel.Server": [], + "Phoenix.Socket.PoolDrainer": [], + "Phoenix.Controller": [ + { + "line": 16, + "name": "layout", + "params": [], + "kind": "type", + "definition": "@type layout() :: {module(), atom()} | false" + }, + { + "line": 15, + "name": "view", + "params": [], + "kind": "type", + "definition": "@type view() :: atom()" + } + ], + "Phoenix.Param.Float": [], + "Phoenix.Endpoint.Watcher": [], + "Mix.Tasks.Phx.Gen.Socket": [], + "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": [ + { + "line": 6, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Mix.Tasks.Phx.Gen.Auth.HashingLibrary, mix_dependency: binary(), module: module(), name: atom(), test_config: binary()}" + } + ], + "Phoenix.Router.NoRouteError": [], + "Phoenix.Router.Helpers": [], + "Phoenix.CodeReloader.Proxy": [], + "Phoenix.ActionClauseError": [], + "Phoenix.Socket": [ + { + "line": 273, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Socket, assigns: map(), channel: atom(), channel_pid: pid(), endpoint: atom(), handler: atom(), id: String.t() | nil, join_ref: term(), joined: boolean(), private: map(), pubsub_server: atom(), ref: term(), serializer: atom(), topic: String.t(), transport: atom(), transport_pid: pid()}" + } + ], + "Phoenix.Digester.Gzip": [], + "Phoenix": [], + "Mix.Tasks.Phx.Gen.Channel": [], + "Phoenix.Socket.Transport": [ + { + "line": 99, + "name": "state", + "params": [], + "kind": "type", + "definition": "@type state() :: term()" + } + ], + "Phoenix.Naming": [], + "Phoenix.Flash": [], + "Phoenix.Param": [ + { + "line": 1, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: term()" + } + ], + "Mix.Tasks.Phx.Gen": [], + "Mix.Tasks.Phx.Gen.Embedded": [], + "Mix.Tasks.Phx.Gen.Schema": [], + "Phoenix.Socket.Serializer": [], + "Mix.Tasks.Phx.Digest": [], + "Mix.Tasks.Phx.Gen.Html": [], + "Phoenix.Param.Integer": [], + "Phoenix.Endpoint": [ + { + "line": 281, + "name": "msg", + "params": [], + "kind": "type", + "definition": "@type msg() :: map() | {:binary, binary()}" + }, + { + "line": 280, + "name": "event", + "params": [], + "kind": "type", + "definition": "@type event() :: String.t()" + }, + { + "line": 279, + "name": "topic", + "params": [], + "kind": "type", + "definition": "@type topic() :: String.t()" + } + ], + "Phoenix.CodeReloader.Server": [], + "Mix.Phoenix.Scope": [], + "Phoenix.Param.Atom": [], + "Phoenix.Param.Map": [], + "Phoenix.Transports.LongPoll.Server": [], + "Plug.Exception.Phoenix.ActionClauseError": [], + "Phoenix.NotAcceptableError": [], + "Mix.Tasks.Phx.Gen.Release": [], + "Phoenix.Endpoint.SyncCodeReloadPlug": [], + "Phoenix.Param.Any": [], + "Phoenix.Socket.Reply": [ + { + "line": 67, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Socket.Reply, join_ref: term(), payload: term(), ref: term(), status: term(), topic: term()}" + } + ], + "Phoenix.ChannelTest": [], + "Phoenix.Transports.LongPoll": [], + "Phoenix.Endpoint.Supervisor": [], + "Mix.Tasks.Phx.Gen.Secret": [], + "Phoenix.ChannelTest.NoopSerializer": [], + "Phoenix.Router": [], + "Phoenix.Presence": [ + { + "line": 209, + "name": "topic", + "params": [], + "kind": "type", + "definition": "@type topic() :: String.t()" + }, + { + "line": 208, + "name": "presence", + "params": [], + "kind": "type", + "definition": "@type presence() :: %{key: String.t(), meta: map()}" + }, + { + "line": 207, + "name": "presences", + "params": [], + "kind": "type", + "definition": "@type presences() :: %{String.t() => %{metas: [map()]}}" + } + ], + "Phoenix.Endpoint.RenderErrors": [], + "Mix.Phoenix.Schema": [], + "Phoenix.Debug": [], + "Phoenix.Socket.V2.JSONSerializer": [], + "Phoenix.MissingParamError": [], + "Inspect.Phoenix.Socket.Message": [], + "Phoenix.CodeReloader": [], + "Phoenix.Socket.InvalidMessageError": [], + "Phoenix.Socket.V1.JSONSerializer": [], + "Phoenix.Socket.Message": [ + { + "line": 16, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Socket.Message, event: term(), join_ref: term(), payload: term(), ref: term(), topic: term()}" + } + ], + "Phoenix.Controller.Pipeline": [], + "Mix.Tasks.Phx.Server": [], + "Mix.Tasks.Phx.Routes": [], + "Phoenix.ConnTest": [], + "Mix.Tasks.Phx.Gen.Live": [], + "Phoenix.Socket.Broadcast": [ + { + "line": 83, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Socket.Broadcast, event: term(), payload: term(), topic: term()}" + } + ], + "Phoenix.Router.MalformedURIError": [], + "Phoenix.Presence.Tracker": [], + "Phoenix.Transports.WebSocket": [], + "Phoenix.Router.ConsoleFormatter": [], + "Mix.Tasks.Compile.Phoenix": [], + "Phoenix.Socket.PoolSupervisor": [], + "Phoenix.Endpoint.Cowboy2Adapter": [], + "Phoenix.Config": [], + "Phoenix.Digester.Compressor": [], + "Phoenix.Digester": [], + "Phoenix.CodeReloader.MixListener": [], + "Phoenix.VerifiedRoutes": [ + { + "line": 275, + "name": "formatted_route", + "params": [], + "kind": "type", + "definition": "@type formatted_route() :: %{verb: String.t(), path: String.t(), label: String.t()}" + }, + { + "line": 274, + "name": "plug_opts", + "params": [], + "kind": "type", + "definition": "@type plug_opts() :: any()" + } + ], + "Mix.Tasks.Phx.Gen.Json": [], + "Phoenix.Param.BitString": [], + "Mix.Phoenix": [], + "Mix.Phoenix.Context": [], + "Mix.Tasks.Phx.Gen.Context": [], + "Phoenix.Token": [ + { + "line": 113, + "name": "signed_at_opt", + "params": [], + "kind": "type", + "definition": "@type signed_at_opt() :: {:signed_at, pos_integer()}" + }, + { + "line": 112, + "name": "max_age_opt", + "params": [], + "kind": "type", + "definition": "@type max_age_opt() :: {:max_age, pos_integer() | :infinity}" + }, + { + "line": 107, + "name": "shared_opt", + "params": [], + "kind": "type", + "definition": "@type shared_opt() :: {:key_iterations, pos_integer()} | {:key_length, pos_integer()} | {:key_digest, :sha256 | :sha384 | :sha512}" + }, + { + "line": 101, + "name": "context", + "params": [], + "kind": "type", + "definition": "@type context() :: Plug.Conn.t() | %{endpoint: atom(), optional(atom()) => any()} | atom() | binary()" + } + ], + "Phoenix.Router.Scope": [], + "Phoenix.Router.Route": [ + { + "line": 45, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Router.Route, assigns: term(), helper: term(), hosts: term(), kind: term(), line: term(), metadata: term(), path: term(), pipe_through: term(), plug: term(), plug_opts: term(), private: term(), trailing_slash?: term(), verb: term(), warn_on_verify?: term()}" + } + ], + "Mix.Tasks.Phx.Gen.Auth": [], + "Mix.Tasks.Phx.Gen.Auth.Injector": [ + { + "line": 7, + "name": "schema", + "params": [], + "kind": "type", + "definition": "@type schema() :: %{__struct__: Mix.Phoenix.Schema, alias: term(), api_route_prefix: term(), assocs: term(), attrs: term(), binary_id: term(), collection: term(), context_app: term(), defaults: term(), embedded?: term(), file: term(), fixture_params: term(), fixture_unique_functions: term(), generate?: term(), human_plural: term(), human_singular: term(), indexes: term(), migration?: term(), migration_defaults: term(), migration_module: term(), module: term(), optionals: term(), opts: term(), params: term(), plural: term(), prefix: term(), redacts: term(), repo: term(), repo_alias: term(), route_helper: term(), route_prefix: term(), sample_id: term(), scope: term(), singular: term(), string_attr: term(), table: term(), timestamp_type: term(), types: term(), uniques: term(), web_namespace: term(), web_path: term()}" + } + ], + "Mix.Tasks.Phx": [], + "Phoenix.Router.Resource": [ + { + "line": 25, + "name": "t", + "params": [], + "kind": "type", + "definition": "@type t() :: %{__struct__: Phoenix.Router.Resource, actions: term(), collection: term(), controller: term(), member: term(), param: term(), path: term(), route: term(), singleton: term()}" + } + ], + "Mix.Tasks.Phx.Gen.Cert": [], + "Mix.Tasks.Phx.Gen.Auth.Migration": [], + "Mix.Tasks.Phx.Gen.Presence": [], + "Mix.Tasks.Phx.Digest.Clean": [] + }, + "extraction_metadata": { + "modules_processed": 92, + "modules_with_debug_info": 92, + "modules_without_debug_info": 0, + "total_calls": 1513, + "total_functions": 1633, + "extraction_time_ms": 165, + "total_specs": 260, + "total_types": 27, + "total_structs": 19 + }, + "generated_at": "2025-12-09T22:19:05.291943Z" +} diff --git a/db/src/fixtures/mod.rs b/db/src/fixtures/mod.rs new file mode 100644 index 0000000..c61a082 --- /dev/null +++ b/db/src/fixtures/mod.rs @@ -0,0 +1,74 @@ +//! Test fixtures for execute tests. +//! +//! This module provides JSON fixtures for testing commands. Fixtures are +//! loaded at compile time using `include_str!` for zero runtime overhead. +//! +//! ## Available Fixtures +//! +//! - [`CALL_GRAPH`] - Function locations and call relationships +//! - [`TYPE_SIGNATURES`] - Function type signatures +//! - [`STRUCTS`] - Struct definitions with fields +//! +//! ## Usage +//! +//! ```ignore +//! use crate::fixtures; +//! +//! crate::execute_test_fixture! { +//! fixture_name: populated_db, +//! json: fixtures::CALL_GRAPH, +//! project: "test_project", +//! } +//! ``` + +/// Call graph fixture with function locations and call relationships. +/// +/// Contains: +/// - 5 modules: Controller, Accounts, Service, Repo, Notifier +/// - 15 functions with various arities and kinds (def/defp) +/// - 11 call edges forming a realistic call graph +/// +/// Use for: trace, reverse_trace, calls_from, calls_to, path, hotspots, +/// unused, depends_on, depended_by +pub const CALL_GRAPH: &str = include_str!("call_graph.json"); + +/// Type signatures fixture with function specs. +/// +/// Contains: +/// - 3 modules: Accounts, Users, Repo +/// - 9 function signatures with typed arguments and return types +/// +/// Use for: search (functions kind), function +pub const TYPE_SIGNATURES: &str = include_str!("type_signatures.json"); + +/// Struct definitions fixture. +/// +/// Contains: +/// - 3 structs: User, Post, Comment +/// - Various field types with defaults and required flags +/// +/// Use for: struct command +pub const STRUCTS: &str = include_str!("structs.json"); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_call_graph_is_valid_json() { + let _: serde_json::Value = serde_json::from_str(CALL_GRAPH) + .expect("CALL_GRAPH should be valid JSON"); + } + + #[test] + fn test_type_signatures_is_valid_json() { + let _: serde_json::Value = serde_json::from_str(TYPE_SIGNATURES) + .expect("TYPE_SIGNATURES should be valid JSON"); + } + + #[test] + fn test_structs_is_valid_json() { + let _: serde_json::Value = serde_json::from_str(STRUCTS) + .expect("STRUCTS should be valid JSON"); + } +} diff --git a/db/src/fixtures/output/calls_from/empty.toon b/db/src/fixtures/output/calls_from/empty.toon new file mode 100644 index 0000000..17638e5 --- /dev/null +++ b/db/src/fixtures/output/calls_from/empty.toon @@ -0,0 +1,4 @@ +function_pattern: get_user +items[0]: +module_pattern: MyApp.Accounts +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/calls_from/single.json b/db/src/fixtures/output/calls_from/single.json new file mode 100644 index 0000000..624f34a --- /dev/null +++ b/db/src/fixtures/output/calls_from/single.json @@ -0,0 +1,40 @@ +{ + "module_pattern": "MyApp.Accounts", + "function_pattern": "get_user", + "total_items": 1, + "items": [ + { + "name": "MyApp.Accounts", + "file": "lib/my_app/accounts.ex", + "entries": [ + { + "name": "get_user", + "arity": 1, + "kind": "", + "start_line": 10, + "end_line": 15, + "calls": [ + { + "caller": { + "module": "MyApp.Accounts", + "name": "get_user", + "arity": 1, + "kind": "", + "file": "lib/my_app/accounts.ex", + "start_line": 10, + "end_line": 15 + }, + "callee": { + "module": "MyApp.Repo", + "name": "get", + "arity": 2 + }, + "line": 12, + "call_type": "remote" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/calls_from/single.toon b/db/src/fixtures/output/calls_from/single.toon new file mode 100644 index 0000000..9700867 --- /dev/null +++ b/db/src/fixtures/output/calls_from/single.toon @@ -0,0 +1,27 @@ +function_pattern: get_user +items[1]: + - entries[1]: + - arity: 1 + calls[1]: + - call_type: remote + callee: + arity: 2 + module: MyApp.Repo + name: get + caller: + arity: 1 + end_line: 15 + file: lib/my_app/accounts.ex + kind: "" + module: MyApp.Accounts + name: get_user + start_line: 10 + line: 12 + end_line: 15 + kind: "" + name: get_user + start_line: 10 + file: lib/my_app/accounts.ex + name: MyApp.Accounts +module_pattern: MyApp.Accounts +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/calls_to/empty.toon b/db/src/fixtures/output/calls_to/empty.toon new file mode 100644 index 0000000..28bbe1a --- /dev/null +++ b/db/src/fixtures/output/calls_to/empty.toon @@ -0,0 +1,4 @@ +function_pattern: get +items[0]: +module_pattern: MyApp.Repo +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/calls_to/single.json b/db/src/fixtures/output/calls_to/single.json new file mode 100644 index 0000000..4f0a32d --- /dev/null +++ b/db/src/fixtures/output/calls_to/single.json @@ -0,0 +1,36 @@ +{ + "module_pattern": "MyApp.Repo", + "function_pattern": "get", + "total_items": 1, + "items": [ + { + "name": "MyApp.Repo", + "entries": [ + { + "name": "get", + "arity": 2, + "callers": [ + { + "caller": { + "module": "MyApp.Accounts", + "name": "get_user", + "arity": 1, + "kind": "", + "file": "lib/my_app/accounts.ex", + "start_line": 10, + "end_line": 15 + }, + "callee": { + "module": "MyApp.Repo", + "name": "get", + "arity": 2 + }, + "line": 12, + "call_type": "remote" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/calls_to/single.toon b/db/src/fixtures/output/calls_to/single.toon new file mode 100644 index 0000000..faa89e8 --- /dev/null +++ b/db/src/fixtures/output/calls_to/single.toon @@ -0,0 +1,23 @@ +function_pattern: get +items[1]: + - entries[1]: + - arity: 2 + callers[1]: + - call_type: remote + callee: + arity: 2 + module: MyApp.Repo + name: get + caller: + arity: 1 + end_line: 15 + file: lib/my_app/accounts.ex + kind: "" + module: MyApp.Accounts + name: get_user + start_line: 10 + line: 12 + name: get + name: MyApp.Repo +module_pattern: MyApp.Repo +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/depended_by/empty.toon b/db/src/fixtures/output/depended_by/empty.toon new file mode 100644 index 0000000..79c4726 --- /dev/null +++ b/db/src/fixtures/output/depended_by/empty.toon @@ -0,0 +1,3 @@ +items[0]: +module_pattern: MyApp.Repo +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/depended_by/single.json b/db/src/fixtures/output/depended_by/single.json new file mode 100644 index 0000000..d019661 --- /dev/null +++ b/db/src/fixtures/output/depended_by/single.json @@ -0,0 +1,26 @@ +{ + "module_pattern": "MyApp.Repo", + "total_items": 1, + "items": [ + { + "name": "MyApp.Service", + "entries": [ + { + "function": "fetch", + "arity": 1, + "kind": "def", + "start_line": 10, + "end_line": 20, + "file": "lib/service.ex", + "targets": [ + { + "function": "get", + "arity": 2, + "line": 15 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/depended_by/single.toon b/db/src/fixtures/output/depended_by/single.toon new file mode 100644 index 0000000..7c5689b --- /dev/null +++ b/db/src/fixtures/output/depended_by/single.toon @@ -0,0 +1,13 @@ +items[1]: + - entries[1]: + - arity: 1 + end_line: 20 + file: lib/service.ex + function: fetch + kind: def + start_line: 10 + targets[1]{arity,function,line}: + 2,get,15 + name: MyApp.Service +module_pattern: MyApp.Repo +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/depends_on/empty.toon b/db/src/fixtures/output/depends_on/empty.toon new file mode 100644 index 0000000..69400de --- /dev/null +++ b/db/src/fixtures/output/depends_on/empty.toon @@ -0,0 +1,3 @@ +items[0]: +module_pattern: MyApp.Controller +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/depends_on/single.json b/db/src/fixtures/output/depends_on/single.json new file mode 100644 index 0000000..7fea175 --- /dev/null +++ b/db/src/fixtures/output/depends_on/single.json @@ -0,0 +1,34 @@ +{ + "module_pattern": "MyApp.Controller", + "total_items": 1, + "items": [ + { + "name": "MyApp.Service", + "entries": [ + { + "name": "process", + "arity": 1, + "callers": [ + { + "caller": { + "module": "MyApp.Controller", + "name": "index", + "arity": 1, + "kind": "def", + "file": "lib/controller.ex", + "start_line": 5, + "end_line": 12 + }, + "callee": { + "module": "MyApp.Service", + "name": "process", + "arity": 1 + }, + "line": 7 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/depends_on/single.toon b/db/src/fixtures/output/depends_on/single.toon new file mode 100644 index 0000000..9f2bbbb --- /dev/null +++ b/db/src/fixtures/output/depends_on/single.toon @@ -0,0 +1,21 @@ +items[1]: + - entries[1]: + - arity: 1 + callers[1]: + - callee: + arity: 1 + module: MyApp.Service + name: process + caller: + arity: 1 + end_line: 12 + file: lib/controller.ex + kind: def + module: MyApp.Controller + name: index + start_line: 5 + line: 7 + name: process + name: MyApp.Service +module_pattern: MyApp.Controller +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/function/empty.toon b/db/src/fixtures/output/function/empty.toon new file mode 100644 index 0000000..17638e5 --- /dev/null +++ b/db/src/fixtures/output/function/empty.toon @@ -0,0 +1,4 @@ +function_pattern: get_user +items[0]: +module_pattern: MyApp.Accounts +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/function/single.json b/db/src/fixtures/output/function/single.json new file mode 100644 index 0000000..4098463 --- /dev/null +++ b/db/src/fixtures/output/function/single.json @@ -0,0 +1,18 @@ +{ + "module_pattern": "MyApp.Accounts", + "function_pattern": "get_user", + "total_items": 1, + "items": [ + { + "name": "MyApp.Accounts", + "entries": [ + { + "name": "get_user", + "arity": 1, + "args": "integer()", + "return_type": "User.t() | nil" + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/function/single.toon b/db/src/fixtures/output/function/single.toon new file mode 100644 index 0000000..4bdacfa --- /dev/null +++ b/db/src/fixtures/output/function/single.toon @@ -0,0 +1,7 @@ +function_pattern: get_user +items[1]: + - entries[1]{args,arity,name,return_type}: + integer(),1,get_user,User.t() | nil + name: MyApp.Accounts +module_pattern: MyApp.Accounts +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/hotspots/empty.toon b/db/src/fixtures/output/hotspots/empty.toon new file mode 100644 index 0000000..c0f122d --- /dev/null +++ b/db/src/fixtures/output/hotspots/empty.toon @@ -0,0 +1,4 @@ +items[0]: +kind_filter: total +module_pattern: * +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/hotspots/single.json b/db/src/fixtures/output/hotspots/single.json new file mode 100644 index 0000000..479fd44 --- /dev/null +++ b/db/src/fixtures/output/hotspots/single.json @@ -0,0 +1,19 @@ +{ + "module_pattern": "*", + "kind_filter": "total", + "total_items": 1, + "items": [ + { + "name": "MyApp.Accounts", + "entries": [ + { + "function": "get_user", + "incoming": 3, + "outgoing": 1, + "total": 4, + "ratio": 3.0 + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/hotspots/single.toon b/db/src/fixtures/output/hotspots/single.toon new file mode 100644 index 0000000..d354591 --- /dev/null +++ b/db/src/fixtures/output/hotspots/single.toon @@ -0,0 +1,7 @@ +items[1]: + - entries[1]{function,incoming,outgoing,ratio,total}: + get_user,3,1,3,4 + name: MyApp.Accounts +kind_filter: total +module_pattern: * +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/import/full.json b/db/src/fixtures/output/import/full.json new file mode 100644 index 0000000..9b19eb0 --- /dev/null +++ b/db/src/fixtures/output/import/full.json @@ -0,0 +1,19 @@ +{ + "schemas": { + "created": [ + "modules", + "functions" + ], + "already_existed": [ + "calls" + ] + }, + "cleared": true, + "modules_imported": 10, + "functions_imported": 50, + "calls_imported": 100, + "structs_imported": 5, + "function_locations_imported": 45, + "specs_imported": 25, + "types_imported": 12 +} \ No newline at end of file diff --git a/db/src/fixtures/output/import/full.toon b/db/src/fixtures/output/import/full.toon new file mode 100644 index 0000000..987381d --- /dev/null +++ b/db/src/fixtures/output/import/full.toon @@ -0,0 +1,11 @@ +calls_imported: 100 +cleared: true +function_locations_imported: 45 +functions_imported: 50 +modules_imported: 10 +schemas: + already_existed[1]: calls + created[2]: modules,functions +specs_imported: 25 +structs_imported: 5 +types_imported: 12 \ No newline at end of file diff --git a/db/src/fixtures/output/location/empty.toon b/db/src/fixtures/output/location/empty.toon new file mode 100644 index 0000000..1b13069 --- /dev/null +++ b/db/src/fixtures/output/location/empty.toon @@ -0,0 +1,4 @@ +function_pattern: foo +module_pattern: MyApp +modules[0]: +total_clauses: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/location/single.json b/db/src/fixtures/output/location/single.json new file mode 100644 index 0000000..8a73ecb --- /dev/null +++ b/db/src/fixtures/output/location/single.json @@ -0,0 +1,25 @@ +{ + "module_pattern": "MyApp.Accounts", + "function_pattern": "get_user", + "total_clauses": 1, + "modules": [ + { + "name": "MyApp.Accounts", + "functions": [ + { + "name": "get_user", + "arity": 1, + "kind": "def", + "file": "lib/my_app/accounts.ex", + "clauses": [ + { + "line": 10, + "start_line": 10, + "end_line": 15 + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/location/single.toon b/db/src/fixtures/output/location/single.toon new file mode 100644 index 0000000..dba5f82 --- /dev/null +++ b/db/src/fixtures/output/location/single.toon @@ -0,0 +1,12 @@ +function_pattern: get_user +module_pattern: MyApp.Accounts +modules[1]: + - functions[1]: + - arity: 1 + clauses[1]{end_line,line,start_line}: + 15,10,10 + file: lib/my_app/accounts.ex + kind: def + name: get_user + name: MyApp.Accounts +total_clauses: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/path/empty.toon b/db/src/fixtures/output/path/empty.toon new file mode 100644 index 0000000..c311e6c --- /dev/null +++ b/db/src/fixtures/output/path/empty.toon @@ -0,0 +1,6 @@ +from_function: index +from_module: MyApp.Controller +max_depth: 10 +paths[0]: +to_function: get +to_module: MyApp.Repo \ No newline at end of file diff --git a/db/src/fixtures/output/path/single.json b/db/src/fixtures/output/path/single.json new file mode 100644 index 0000000..188977d --- /dev/null +++ b/db/src/fixtures/output/path/single.json @@ -0,0 +1,33 @@ +{ + "from_module": "MyApp.Controller", + "from_function": "index", + "to_module": "MyApp.Repo", + "to_function": "get", + "max_depth": 10, + "paths": [ + { + "steps": [ + { + "depth": 1, + "caller_module": "MyApp.Controller", + "caller_function": "index", + "callee_module": "MyApp.Service", + "callee_function": "fetch", + "callee_arity": 1, + "file": "lib/controller.ex", + "line": 7 + }, + { + "depth": 2, + "caller_module": "MyApp.Service", + "caller_function": "fetch", + "callee_module": "MyApp.Repo", + "callee_function": "get", + "callee_arity": 2, + "file": "lib/service.ex", + "line": 15 + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/path/single.toon b/db/src/fixtures/output/path/single.toon new file mode 100644 index 0000000..55f3c95 --- /dev/null +++ b/db/src/fixtures/output/path/single.toon @@ -0,0 +1,9 @@ +from_function: index +from_module: MyApp.Controller +max_depth: 10 +paths[1]: + - steps[2]{callee_arity,callee_function,callee_module,caller_function,caller_module,depth,file,line}: + 1,fetch,MyApp.Service,index,MyApp.Controller,1,lib/controller.ex,7 + 2,get,MyApp.Repo,fetch,MyApp.Service,2,lib/service.ex,15 +to_function: get +to_module: MyApp.Repo \ No newline at end of file diff --git a/db/src/fixtures/output/reverse_trace/empty.toon b/db/src/fixtures/output/reverse_trace/empty.toon new file mode 100644 index 0000000..94178bb --- /dev/null +++ b/db/src/fixtures/output/reverse_trace/empty.toon @@ -0,0 +1,5 @@ +max_depth: 5 +roots[0]: +target_function: get +target_module: MyApp.Repo +total_callers: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/reverse_trace/single.json b/db/src/fixtures/output/reverse_trace/single.json new file mode 100644 index 0000000..5bff18d --- /dev/null +++ b/db/src/fixtures/output/reverse_trace/single.json @@ -0,0 +1,25 @@ +{ + "target_module": "MyApp.Repo", + "target_function": "get", + "max_depth": 5, + "total_callers": 1, + "roots": [ + { + "module": "MyApp.Service", + "function": "fetch", + "arity": 1, + "kind": "def", + "start_line": 10, + "end_line": 20, + "file": "lib/service.ex", + "targets": [ + { + "module": "MyApp.Repo", + "function": "get", + "arity": 2, + "line": 15 + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/reverse_trace/single.toon b/db/src/fixtures/output/reverse_trace/single.toon new file mode 100644 index 0000000..e0244da --- /dev/null +++ b/db/src/fixtures/output/reverse_trace/single.toon @@ -0,0 +1,14 @@ +max_depth: 5 +roots[1]: + - arity: 1 + end_line: 20 + file: lib/service.ex + function: fetch + kind: def + module: MyApp.Service + start_line: 10 + targets[1]{arity,function,line,module}: + 2,get,15,MyApp.Repo +target_function: get +target_module: MyApp.Repo +total_callers: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/search/empty.toon b/db/src/fixtures/output/search/empty.toon new file mode 100644 index 0000000..d112498 --- /dev/null +++ b/db/src/fixtures/output/search/empty.toon @@ -0,0 +1,2 @@ +kind: modules +pattern: test \ No newline at end of file diff --git a/db/src/fixtures/output/search/modules.json b/db/src/fixtures/output/search/modules.json new file mode 100644 index 0000000..6560dc4 --- /dev/null +++ b/db/src/fixtures/output/search/modules.json @@ -0,0 +1,16 @@ +{ + "pattern": "MyApp", + "kind": "modules", + "modules": [ + { + "project": "default", + "name": "MyApp.Accounts", + "source": "unknown" + }, + { + "project": "default", + "name": "MyApp.Users", + "source": "unknown" + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/search/modules.toon b/db/src/fixtures/output/search/modules.toon new file mode 100644 index 0000000..fb639a1 --- /dev/null +++ b/db/src/fixtures/output/search/modules.toon @@ -0,0 +1,5 @@ +kind: modules +modules[2]{name,project,source}: + MyApp.Accounts,default,unknown + MyApp.Users,default,unknown +pattern: MyApp \ No newline at end of file diff --git a/db/src/fixtures/output/trace/empty.toon b/db/src/fixtures/output/trace/empty.toon new file mode 100644 index 0000000..8f5c9e2 --- /dev/null +++ b/db/src/fixtures/output/trace/empty.toon @@ -0,0 +1,5 @@ +max_depth: 5 +roots[0]: +start_function: index +start_module: MyApp.Controller +total_calls: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/trace/single.json b/db/src/fixtures/output/trace/single.json new file mode 100644 index 0000000..19c6861 --- /dev/null +++ b/db/src/fixtures/output/trace/single.json @@ -0,0 +1,25 @@ +{ + "start_module": "MyApp.Controller", + "start_function": "index", + "max_depth": 5, + "total_calls": 1, + "roots": [ + { + "module": "MyApp.Controller", + "function": "index", + "arity": 1, + "kind": "def", + "start_line": 5, + "end_line": 12, + "file": "lib/controller.ex", + "calls": [ + { + "module": "MyApp.Service", + "function": "fetch", + "arity": 1, + "line": 7 + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/trace/single.toon b/db/src/fixtures/output/trace/single.toon new file mode 100644 index 0000000..d66a2c2 --- /dev/null +++ b/db/src/fixtures/output/trace/single.toon @@ -0,0 +1,14 @@ +max_depth: 5 +roots[1]: + - arity: 1 + calls[1]{arity,function,line,module}: + 1,fetch,7,MyApp.Service + end_line: 12 + file: lib/controller.ex + function: index + kind: def + module: MyApp.Controller + start_line: 5 +start_function: index +start_module: MyApp.Controller +total_calls: 1 \ No newline at end of file diff --git a/db/src/fixtures/output/unused/empty.toon b/db/src/fixtures/output/unused/empty.toon new file mode 100644 index 0000000..4ae260a --- /dev/null +++ b/db/src/fixtures/output/unused/empty.toon @@ -0,0 +1,3 @@ +items[0]: +module_pattern: * +total_items: 0 \ No newline at end of file diff --git a/db/src/fixtures/output/unused/single.json b/db/src/fixtures/output/unused/single.json new file mode 100644 index 0000000..d0ee71e --- /dev/null +++ b/db/src/fixtures/output/unused/single.json @@ -0,0 +1,18 @@ +{ + "module_pattern": "*", + "total_items": 1, + "items": [ + { + "name": "MyApp.Accounts", + "file": "lib/accounts.ex", + "entries": [ + { + "name": "unused_helper", + "arity": 0, + "kind": "defp", + "line": 35 + } + ] + } + ] +} \ No newline at end of file diff --git a/db/src/fixtures/output/unused/single.toon b/db/src/fixtures/output/unused/single.toon new file mode 100644 index 0000000..ac5cf7d --- /dev/null +++ b/db/src/fixtures/output/unused/single.toon @@ -0,0 +1,7 @@ +items[1]: + - entries[1]{arity,kind,line,name}: + 0,defp,35,unused_helper + file: lib/accounts.ex + name: MyApp.Accounts +module_pattern: * +total_items: 1 \ No newline at end of file diff --git a/db/src/fixtures/structs.json b/db/src/fixtures/structs.json new file mode 100644 index 0000000..a272afe --- /dev/null +++ b/db/src/fixtures/structs.json @@ -0,0 +1,33 @@ +{ + "structs": { + "MyApp.User": { + "fields": [ + {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, + {"default": "nil", "field": "name", "required": true, "inferred_type": "String.t()"}, + {"default": "nil", "field": "email", "required": true, "inferred_type": "String.t()"}, + {"default": "false", "field": "admin", "required": false, "inferred_type": "boolean()"}, + {"default": "nil", "field": "inserted_at", "required": false, "inferred_type": "DateTime.t()"} + ] + }, + "MyApp.Post": { + "fields": [ + {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, + {"default": "nil", "field": "title", "required": true, "inferred_type": "String.t()"}, + {"default": "nil", "field": "body", "required": false, "inferred_type": "String.t()"}, + {"default": "nil", "field": "user_id", "required": true, "inferred_type": "integer()"}, + {"default": ":draft", "field": "status", "required": false, "inferred_type": "atom()"} + ] + }, + "MyApp.Comment": { + "fields": [ + {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, + {"default": "nil", "field": "content", "required": true, "inferred_type": "String.t()"}, + {"default": "nil", "field": "post_id", "required": true, "inferred_type": "integer()"}, + {"default": "nil", "field": "user_id", "required": true, "inferred_type": "integer()"} + ] + } + }, + "function_locations": {}, + "calls": [], + "type_signatures": {} +} diff --git a/db/src/fixtures/type_signatures.json b/db/src/fixtures/type_signatures.json new file mode 100644 index 0000000..86dd0db --- /dev/null +++ b/db/src/fixtures/type_signatures.json @@ -0,0 +1,176 @@ +{ + "structs": {}, + "function_locations": {}, + "calls": [], + "type_signatures": {}, + "specs": { + "MyApp.Accounts": [ + { + "arity": 1, + "name": "get_user", + "line": 10, + "kind": "spec", + "clauses": [ + { + "full": "@spec get_user(integer()) :: User.t() | nil", + "input_strings": [ + "integer()" + ], + "return_strings": [ + "User.t()", + "nil" + ] + } + ] + }, + { + "arity": 2, + "name": "get_user", + "line": 15, + "kind": "spec", + "clauses": [ + { + "full": "@spec get_user(integer(), keyword()) :: User.t() | nil", + "input_strings": [ + "integer()", + "keyword()" + ], + "return_strings": [ + "User.t()", + "nil" + ] + } + ] + }, + { + "arity": 0, + "name": "list_users", + "line": 20, + "kind": "spec", + "clauses": [ + { + "full": "@spec list_users() :: [User.t()]", + "input_strings": [], + "return_strings": [ + "[User.t()]" + ] + } + ] + }, + { + "arity": 1, + "name": "create_user", + "line": 25, + "kind": "spec", + "clauses": [ + { + "full": "@spec create_user(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}", + "input_strings": [ + "map()" + ], + "return_strings": [ + "{:ok, User.t()}", + "{:error, Ecto.Changeset.t()}" + ] + } + ] + } + ], + "MyApp.Users": [ + { + "arity": 1, + "name": "get_by_email", + "line": 10, + "kind": "spec", + "clauses": [ + { + "full": "@spec get_by_email(String.t()) :: User.t() | nil", + "input_strings": [ + "String.t()" + ], + "return_strings": [ + "User.t()", + "nil" + ] + } + ] + }, + { + "arity": 2, + "name": "authenticate", + "line": 15, + "kind": "spec", + "clauses": [ + { + "full": "@spec authenticate(String.t(), String.t()) :: {:ok, User.t()} | {:error, atom()}", + "input_strings": [ + "String.t()", + "String.t()" + ], + "return_strings": [ + "{:ok, User.t()}", + "{:error, atom()}" + ] + } + ] + } + ], + "MyApp.Repo": [ + { + "arity": 2, + "name": "get", + "line": 10, + "kind": "spec", + "clauses": [ + { + "full": "@spec get(module(), integer()) :: struct() | nil", + "input_strings": [ + "module()", + "integer()" + ], + "return_strings": [ + "struct()", + "nil" + ] + } + ] + }, + { + "arity": 1, + "name": "all", + "line": 15, + "kind": "spec", + "clauses": [ + { + "full": "@spec all(Ecto.Queryable.t()) :: [struct()]", + "input_strings": [ + "Ecto.Queryable.t()" + ], + "return_strings": [ + "[struct()]" + ] + } + ] + }, + { + "arity": 2, + "name": "insert", + "line": 20, + "kind": "spec", + "clauses": [ + { + "full": "@spec insert(struct(), keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}", + "input_strings": [ + "struct()", + "keyword()" + ], + "return_strings": [ + "{:ok, struct()}", + "{:error, Ecto.Changeset.t()}" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/db/src/lib.rs b/db/src/lib.rs index 733014f..ed2e691 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -5,10 +5,16 @@ pub mod types; pub mod query_builders; pub mod queries; +#[cfg(feature = "test-utils")] +pub mod test_utils; + +#[cfg(feature = "test-utils")] +pub mod fixtures; + // Re-export commonly used items pub use db::{open_db, run_query, run_query_no_params, DbError, Params}; -#[cfg(test)] +#[cfg(any(test, feature = "test-utils"))] pub use db::open_mem_db; pub use types::{ diff --git a/db/src/queries/import.rs b/db/src/queries/import.rs index b7147eb..9e036f2 100644 --- a/db/src/queries/import.rs +++ b/db/src/queries/import.rs @@ -440,7 +440,7 @@ pub fn import_graph( /// Import a JSON string directly into the database. /// /// Convenience wrapper for tests that parses JSON and calls `import_graph`. -#[cfg(test)] +#[cfg(any(test, feature = "test-utils"))] pub fn import_json_str( db: &DbInstance, content: &str, diff --git a/db/src/test_utils.rs b/db/src/test_utils.rs new file mode 100644 index 0000000..9ea9085 --- /dev/null +++ b/db/src/test_utils.rs @@ -0,0 +1,94 @@ +//! Shared test utilities for database and integration tests. +//! +//! This module provides common helpers for setting up test databases with fixture data. + +#[cfg(feature = "test-utils")] +use std::io::Write; + +use cozo::DbInstance; +#[cfg(feature = "test-utils")] +use tempfile::NamedTempFile; + +#[cfg(any(test, feature = "test-utils"))] +use crate::queries::import::import_json_str; +use crate::db::open_mem_db; + +/// Create a temporary file containing the given content. +/// +/// Used to create JSON files for importing test data. +#[cfg(feature = "test-utils")] +pub fn create_temp_json_file(content: &str) -> NamedTempFile { + let mut file = NamedTempFile::new().expect("Failed to create temp file"); + file.write_all(content.as_bytes()) + .expect("Failed to write temp file"); + file +} + +/// Create an in-memory database and import JSON content. +/// +/// This is the standard setup for execute tests: create an in-memory DB, +/// import test data, return the DB instance for command execution. +#[cfg(any(test, feature = "test-utils"))] +pub fn setup_test_db(json_content: &str, project: &str) -> DbInstance { + let db = open_mem_db(); + import_json_str(&db, json_content, project).expect("Import should succeed"); + db +} + +/// Create an empty in-memory database. +/// +/// Used to verify queries fail gracefully on empty DBs. +#[cfg(any(test, feature = "test-utils"))] +pub fn setup_empty_test_db() -> DbInstance { + open_mem_db() +} + +// ============================================================================= +// Fixture-based helpers +// ============================================================================= + +#[cfg(any(test, feature = "test-utils"))] +use crate::fixtures; + +/// Create a test database with call graph data. +/// +/// Use for: trace, reverse_trace, calls_from, calls_to, path, hotspots, +/// unused, depends_on, depended_by +#[cfg(any(test, feature = "test-utils"))] +pub fn call_graph_db(project: &str) -> DbInstance { + setup_test_db(fixtures::CALL_GRAPH, project) +} + +/// Create a test database with type signature data. +/// +/// Use for: search (functions kind), function +#[cfg(any(test, feature = "test-utils"))] +pub fn type_signatures_db(project: &str) -> DbInstance { + setup_test_db(fixtures::TYPE_SIGNATURES, project) +} + +/// Create a test database with struct definitions. +/// +/// Use for: struct command +#[cfg(any(test, feature = "test-utils"))] +pub fn structs_db(project: &str) -> DbInstance { + setup_test_db(fixtures::STRUCTS, project) +} + +// ============================================================================= +// Output fixture helpers +// ============================================================================= + +use std::path::Path; + +/// Load a fixture file from src/fixtures/output// +#[cfg(any(test, feature = "test-utils"))] +pub fn load_output_fixture(command: &str, name: &str) -> String { + let fixture_path = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("src/fixtures/output") + .join(command) + .join(name); + + std::fs::read_to_string(&fixture_path) + .unwrap_or_else(|e| panic!("Failed to read fixture {}: {}", fixture_path.display(), e)) +} From 5d47bcbc110d7269802f2f651f76ebc8c893efb3 Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Tue, 23 Dec 2025 00:00:34 +0100 Subject: [PATCH 6/8] Migrate CLI source files to cli crate Implements ticket 6 of 8 - Migrate CLI source files. Changes: - Copy core CLI files to cli/src/: - main.rs (entry point, module declarations, CLI runner) - cli.rs (clap argument parser) - output.rs (OutputFormat trait, Outputable trait) - dedup.rs (deduplication utilities) - test_macros.rs (test infrastructure macros) - Copy entire commands/ directory to cli/src/commands/ - All 27 command subdirectories with execute.rs, output.rs, models.rs - Create cli/src/utils.rs with presentation logic only: - group_by_module, group_by_module_with_file, group_calls - convert_to_module_groups - format_type_definition and supporting functions - Excluded: ConditionBuilder, OptionalConditionBuilder (moved to db crate) Commands migrated: - accepts, boundaries, browse_module, calls_from, calls_to - clusters, complexity, cycles, depended_by, depends_on - describe, duplicates, function, god_modules, hotspots - import, large_functions, location, many_clauses, path - returns, reverse_trace, search, setup, struct_usage - trace, unused Note: Import paths still point to old crate:: locations and will be updated in ticket 7. The cli crate won't compile yet - this is expected. Original src/ directory preserved for reference. Relates to ticket: scratch/tickets/06-migrate-cli-files.md --- cli/src/cli.rs | 61 ++ cli/src/commands/accepts/execute.rs | 69 ++ cli/src/commands/accepts/mod.rs | 37 + cli/src/commands/accepts/output.rs | 33 + cli/src/commands/boundaries/execute.rs | 103 ++ cli/src/commands/boundaries/mod.rs | 47 + cli/src/commands/boundaries/output.rs | 79 ++ cli/src/commands/browse_module/cli_tests.rs | 115 +++ cli/src/commands/browse_module/execute.rs | 325 +++++++ .../commands/browse_module/execute_tests.rs | 323 +++++++ cli/src/commands/browse_module/mod.rs | 79 ++ cli/src/commands/browse_module/output.rs | 215 +++++ .../commands/browse_module/output_tests.rs | 261 ++++++ cli/src/commands/calls_from/cli_tests.rs | 74 ++ cli/src/commands/calls_from/execute.rs | 101 ++ cli/src/commands/calls_from/execute_tests.rs | 172 ++++ cli/src/commands/calls_from/mod.rs | 41 + cli/src/commands/calls_from/output.rs | 48 + cli/src/commands/calls_from/output_tests.rs | 162 ++++ cli/src/commands/calls_to/cli_tests.rs | 74 ++ cli/src/commands/calls_to/execute.rs | 88 ++ cli/src/commands/calls_to/execute_tests.rs | 202 ++++ cli/src/commands/calls_to/mod.rs | 42 + cli/src/commands/calls_to/output.rs | 41 + cli/src/commands/calls_to/output_tests.rs | 162 ++++ cli/src/commands/clusters/execute.rs | 390 ++++++++ cli/src/commands/clusters/mod.rs | 46 + cli/src/commands/clusters/output.rs | 81 ++ cli/src/commands/complexity/cli_tests.rs | 119 +++ cli/src/commands/complexity/execute.rs | 85 ++ cli/src/commands/complexity/execute_tests.rs | 169 ++++ cli/src/commands/complexity/mod.rs | 59 ++ cli/src/commands/complexity/output.rs | 40 + cli/src/commands/complexity/output_tests.rs | 123 +++ cli/src/commands/cycles/execute.rs | 274 ++++++ cli/src/commands/cycles/mod.rs | 45 + cli/src/commands/cycles/output.rs | 125 +++ cli/src/commands/depended_by/cli_tests.rs | 56 ++ cli/src/commands/depended_by/execute.rs | 127 +++ cli/src/commands/depended_by/execute_tests.rs | 112 +++ cli/src/commands/depended_by/mod.rs | 34 + cli/src/commands/depended_by/output.rs | 48 + cli/src/commands/depended_by/output_tests.rs | 176 ++++ cli/src/commands/depends_on/cli_tests.rs | 56 ++ cli/src/commands/depends_on/execute.rs | 83 ++ cli/src/commands/depends_on/execute_tests.rs | 110 +++ cli/src/commands/depends_on/mod.rs | 34 + cli/src/commands/depends_on/output.rs | 37 + cli/src/commands/depends_on/output_tests.rs | 194 ++++ cli/src/commands/describe/descriptions.rs | 488 ++++++++++ cli/src/commands/describe/execute.rs | 146 +++ cli/src/commands/describe/mod.rs | 30 + cli/src/commands/describe/output.rs | 162 ++++ cli/src/commands/duplicates/cli_tests.rs | 107 +++ cli/src/commands/duplicates/execute.rs | 191 ++++ cli/src/commands/duplicates/execute_tests.rs | 230 +++++ cli/src/commands/duplicates/mod.rs | 49 + cli/src/commands/duplicates/output.rs | 90 ++ cli/src/commands/duplicates/output_tests.rs | 541 +++++++++++ cli/src/commands/function/cli_tests.rs | 88 ++ cli/src/commands/function/execute.rs | 73 ++ cli/src/commands/function/execute_tests.rs | 160 ++++ cli/src/commands/function/mod.rs | 43 + cli/src/commands/function/output.rs | 41 + cli/src/commands/function/output_tests.rs | 152 +++ cli/src/commands/god_modules/execute.rs | 164 ++++ cli/src/commands/god_modules/mod.rs | 51 + cli/src/commands/god_modules/output.rs | 55 ++ cli/src/commands/hotspots/cli_tests.rs | 133 +++ cli/src/commands/hotspots/execute.rs | 142 +++ cli/src/commands/hotspots/execute_tests.rs | 170 ++++ cli/src/commands/hotspots/mod.rs | 56 ++ cli/src/commands/hotspots/output.rs | 4 + cli/src/commands/hotspots/output_tests.rs | 153 +++ cli/src/commands/import/cli_tests.rs | 76 ++ cli/src/commands/import/execute.rs | 247 +++++ cli/src/commands/import/mod.rs | 50 + cli/src/commands/import/output.rs | 32 + cli/src/commands/import/output_tests.rs | 119 +++ cli/src/commands/large_functions/execute.rs | 108 +++ cli/src/commands/large_functions/mod.rs | 46 + cli/src/commands/large_functions/output.rs | 40 + cli/src/commands/location/cli_tests.rs | 91 ++ cli/src/commands/location/execute.rs | 131 +++ cli/src/commands/location/execute_tests.rs | 320 +++++++ cli/src/commands/location/mod.rs | 44 + cli/src/commands/location/output.rs | 54 ++ cli/src/commands/location/output_tests.rs | 169 ++++ cli/src/commands/many_clauses/execute.rs | 107 +++ cli/src/commands/many_clauses/mod.rs | 47 + cli/src/commands/many_clauses/output.rs | 40 + cli/src/commands/mod.rs | 209 +++++ cli/src/commands/path/cli_tests.rs | 187 ++++ cli/src/commands/path/execute.rs | 48 + cli/src/commands/path/execute_tests.rs | 209 +++++ cli/src/commands/path/mod.rs | 66 ++ cli/src/commands/path/output.rs | 39 + cli/src/commands/path/output_tests.rs | 122 +++ cli/src/commands/returns/execute.rs | 67 ++ cli/src/commands/returns/mod.rs | 37 + cli/src/commands/returns/output.rs | 30 + cli/src/commands/reverse_trace/cli_tests.rs | 115 +++ cli/src/commands/reverse_trace/execute.rs | 157 ++++ .../commands/reverse_trace/execute_tests.rs | 120 +++ cli/src/commands/reverse_trace/mod.rs | 47 + cli/src/commands/reverse_trace/output.rs | 4 + .../commands/reverse_trace/output_tests.rs | 138 +++ cli/src/commands/search/cli_tests.rs | 92 ++ cli/src/commands/search/execute.rs | 93 ++ cli/src/commands/search/execute_tests.rs | 204 ++++ cli/src/commands/search/mod.rs | 50 + cli/src/commands/search/output.rs | 48 + cli/src/commands/search/output_tests.rs | 137 +++ cli/src/commands/setup/execute.rs | 887 ++++++++++++++++++ cli/src/commands/setup/mod.rs | 54 ++ cli/src/commands/setup/output.rs | 189 ++++ cli/src/commands/struct_usage/cli_tests.rs | 91 ++ cli/src/commands/struct_usage/execute.rs | 177 ++++ .../commands/struct_usage/execute_tests.rs | 228 +++++ cli/src/commands/struct_usage/mod.rs | 49 + cli/src/commands/struct_usage/output.rs | 140 +++ cli/src/commands/struct_usage/output_tests.rs | 172 ++++ cli/src/commands/trace/cli_tests.rs | 117 +++ cli/src/commands/trace/execute.rs | 179 ++++ cli/src/commands/trace/execute_tests.rs | 124 +++ cli/src/commands/trace/mod.rs | 47 + cli/src/commands/trace/output.rs | 179 ++++ cli/src/commands/trace/output_tests.rs | 165 ++++ cli/src/commands/unused/cli_tests.rs | 135 +++ cli/src/commands/unused/execute.rs | 70 ++ cli/src/commands/unused/execute_tests.rs | 195 ++++ cli/src/commands/unused/mod.rs | 50 + cli/src/commands/unused/output.rs | 43 + cli/src/commands/unused/output_tests.rs | 143 +++ cli/src/dedup.rs | 112 +++ cli/src/main.rs | 36 +- cli/src/output.rs | 186 ++++ cli/src/test_macros.rs | 658 +++++++++++++ cli/src/utils.rs | 490 ++++++++++ 139 files changed, 17948 insertions(+), 4 deletions(-) create mode 100644 cli/src/cli.rs create mode 100644 cli/src/commands/accepts/execute.rs create mode 100644 cli/src/commands/accepts/mod.rs create mode 100644 cli/src/commands/accepts/output.rs create mode 100644 cli/src/commands/boundaries/execute.rs create mode 100644 cli/src/commands/boundaries/mod.rs create mode 100644 cli/src/commands/boundaries/output.rs create mode 100644 cli/src/commands/browse_module/cli_tests.rs create mode 100644 cli/src/commands/browse_module/execute.rs create mode 100644 cli/src/commands/browse_module/execute_tests.rs create mode 100644 cli/src/commands/browse_module/mod.rs create mode 100644 cli/src/commands/browse_module/output.rs create mode 100644 cli/src/commands/browse_module/output_tests.rs create mode 100644 cli/src/commands/calls_from/cli_tests.rs create mode 100644 cli/src/commands/calls_from/execute.rs create mode 100644 cli/src/commands/calls_from/execute_tests.rs create mode 100644 cli/src/commands/calls_from/mod.rs create mode 100644 cli/src/commands/calls_from/output.rs create mode 100644 cli/src/commands/calls_from/output_tests.rs create mode 100644 cli/src/commands/calls_to/cli_tests.rs create mode 100644 cli/src/commands/calls_to/execute.rs create mode 100644 cli/src/commands/calls_to/execute_tests.rs create mode 100644 cli/src/commands/calls_to/mod.rs create mode 100644 cli/src/commands/calls_to/output.rs create mode 100644 cli/src/commands/calls_to/output_tests.rs create mode 100644 cli/src/commands/clusters/execute.rs create mode 100644 cli/src/commands/clusters/mod.rs create mode 100644 cli/src/commands/clusters/output.rs create mode 100644 cli/src/commands/complexity/cli_tests.rs create mode 100644 cli/src/commands/complexity/execute.rs create mode 100644 cli/src/commands/complexity/execute_tests.rs create mode 100644 cli/src/commands/complexity/mod.rs create mode 100644 cli/src/commands/complexity/output.rs create mode 100644 cli/src/commands/complexity/output_tests.rs create mode 100644 cli/src/commands/cycles/execute.rs create mode 100644 cli/src/commands/cycles/mod.rs create mode 100644 cli/src/commands/cycles/output.rs create mode 100644 cli/src/commands/depended_by/cli_tests.rs create mode 100644 cli/src/commands/depended_by/execute.rs create mode 100644 cli/src/commands/depended_by/execute_tests.rs create mode 100644 cli/src/commands/depended_by/mod.rs create mode 100644 cli/src/commands/depended_by/output.rs create mode 100644 cli/src/commands/depended_by/output_tests.rs create mode 100644 cli/src/commands/depends_on/cli_tests.rs create mode 100644 cli/src/commands/depends_on/execute.rs create mode 100644 cli/src/commands/depends_on/execute_tests.rs create mode 100644 cli/src/commands/depends_on/mod.rs create mode 100644 cli/src/commands/depends_on/output.rs create mode 100644 cli/src/commands/depends_on/output_tests.rs create mode 100644 cli/src/commands/describe/descriptions.rs create mode 100644 cli/src/commands/describe/execute.rs create mode 100644 cli/src/commands/describe/mod.rs create mode 100644 cli/src/commands/describe/output.rs create mode 100644 cli/src/commands/duplicates/cli_tests.rs create mode 100644 cli/src/commands/duplicates/execute.rs create mode 100644 cli/src/commands/duplicates/execute_tests.rs create mode 100644 cli/src/commands/duplicates/mod.rs create mode 100644 cli/src/commands/duplicates/output.rs create mode 100644 cli/src/commands/duplicates/output_tests.rs create mode 100644 cli/src/commands/function/cli_tests.rs create mode 100644 cli/src/commands/function/execute.rs create mode 100644 cli/src/commands/function/execute_tests.rs create mode 100644 cli/src/commands/function/mod.rs create mode 100644 cli/src/commands/function/output.rs create mode 100644 cli/src/commands/function/output_tests.rs create mode 100644 cli/src/commands/god_modules/execute.rs create mode 100644 cli/src/commands/god_modules/mod.rs create mode 100644 cli/src/commands/god_modules/output.rs create mode 100644 cli/src/commands/hotspots/cli_tests.rs create mode 100644 cli/src/commands/hotspots/execute.rs create mode 100644 cli/src/commands/hotspots/execute_tests.rs create mode 100644 cli/src/commands/hotspots/mod.rs create mode 100644 cli/src/commands/hotspots/output.rs create mode 100644 cli/src/commands/hotspots/output_tests.rs create mode 100644 cli/src/commands/import/cli_tests.rs create mode 100644 cli/src/commands/import/execute.rs create mode 100644 cli/src/commands/import/mod.rs create mode 100644 cli/src/commands/import/output.rs create mode 100644 cli/src/commands/import/output_tests.rs create mode 100644 cli/src/commands/large_functions/execute.rs create mode 100644 cli/src/commands/large_functions/mod.rs create mode 100644 cli/src/commands/large_functions/output.rs create mode 100644 cli/src/commands/location/cli_tests.rs create mode 100644 cli/src/commands/location/execute.rs create mode 100644 cli/src/commands/location/execute_tests.rs create mode 100644 cli/src/commands/location/mod.rs create mode 100644 cli/src/commands/location/output.rs create mode 100644 cli/src/commands/location/output_tests.rs create mode 100644 cli/src/commands/many_clauses/execute.rs create mode 100644 cli/src/commands/many_clauses/mod.rs create mode 100644 cli/src/commands/many_clauses/output.rs create mode 100644 cli/src/commands/mod.rs create mode 100644 cli/src/commands/path/cli_tests.rs create mode 100644 cli/src/commands/path/execute.rs create mode 100644 cli/src/commands/path/execute_tests.rs create mode 100644 cli/src/commands/path/mod.rs create mode 100644 cli/src/commands/path/output.rs create mode 100644 cli/src/commands/path/output_tests.rs create mode 100644 cli/src/commands/returns/execute.rs create mode 100644 cli/src/commands/returns/mod.rs create mode 100644 cli/src/commands/returns/output.rs create mode 100644 cli/src/commands/reverse_trace/cli_tests.rs create mode 100644 cli/src/commands/reverse_trace/execute.rs create mode 100644 cli/src/commands/reverse_trace/execute_tests.rs create mode 100644 cli/src/commands/reverse_trace/mod.rs create mode 100644 cli/src/commands/reverse_trace/output.rs create mode 100644 cli/src/commands/reverse_trace/output_tests.rs create mode 100644 cli/src/commands/search/cli_tests.rs create mode 100644 cli/src/commands/search/execute.rs create mode 100644 cli/src/commands/search/execute_tests.rs create mode 100644 cli/src/commands/search/mod.rs create mode 100644 cli/src/commands/search/output.rs create mode 100644 cli/src/commands/search/output_tests.rs create mode 100644 cli/src/commands/setup/execute.rs create mode 100644 cli/src/commands/setup/mod.rs create mode 100644 cli/src/commands/setup/output.rs create mode 100644 cli/src/commands/struct_usage/cli_tests.rs create mode 100644 cli/src/commands/struct_usage/execute.rs create mode 100644 cli/src/commands/struct_usage/execute_tests.rs create mode 100644 cli/src/commands/struct_usage/mod.rs create mode 100644 cli/src/commands/struct_usage/output.rs create mode 100644 cli/src/commands/struct_usage/output_tests.rs create mode 100644 cli/src/commands/trace/cli_tests.rs create mode 100644 cli/src/commands/trace/execute.rs create mode 100644 cli/src/commands/trace/execute_tests.rs create mode 100644 cli/src/commands/trace/mod.rs create mode 100644 cli/src/commands/trace/output.rs create mode 100644 cli/src/commands/trace/output_tests.rs create mode 100644 cli/src/commands/unused/cli_tests.rs create mode 100644 cli/src/commands/unused/execute.rs create mode 100644 cli/src/commands/unused/execute_tests.rs create mode 100644 cli/src/commands/unused/mod.rs create mode 100644 cli/src/commands/unused/output.rs create mode 100644 cli/src/commands/unused/output_tests.rs create mode 100644 cli/src/dedup.rs create mode 100644 cli/src/output.rs create mode 100644 cli/src/test_macros.rs create mode 100644 cli/src/utils.rs diff --git a/cli/src/cli.rs b/cli/src/cli.rs new file mode 100644 index 0000000..e4a33b9 --- /dev/null +++ b/cli/src/cli.rs @@ -0,0 +1,61 @@ +//! CLI argument definitions. +//! +//! This module contains the top-level CLI structure and shared types. +//! Individual command definitions are in the `commands` module. + +use clap::Parser; +use std::path::PathBuf; + +use crate::commands::Command; +use crate::output::OutputFormat; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct Args { + /// Path to the CozoDB SQLite database file + /// + /// If not specified, searches for database in: + /// 1. .code_search/cozo.sqlite (project-local) + /// 2. ./cozo.sqlite (current directory) + /// 3. ~/.code_search/cozo.sqlite (user-global) + #[arg(long, global = true)] + pub db: Option, + + /// Output format + #[arg(short = 'o', long, value_enum, default_value_t = OutputFormat::Table, global = true)] + pub format: OutputFormat, + + #[command(subcommand)] + pub command: Command, +} + +/// Resolve database path by checking multiple locations in order of preference +pub fn resolve_db_path(explicit_path: Option) -> PathBuf { + // If explicitly specified, use that + if let Some(path) = explicit_path { + return path; + } + + // 1. Check .code_search/cozo.sqlite (project-local) + let project_db = PathBuf::from(".code_search/cozo.sqlite"); + if project_db.exists() { + return project_db; + } + + // 2. Check ./cozo.sqlite (current directory) + let local_db = PathBuf::from("./cozo.sqlite"); + if local_db.exists() { + return local_db; + } + + // 3. Check ~/.code_search/cozo.sqlite (user-global) + if let Some(home_dir) = home::home_dir() { + let global_db = home_dir.join(".code_search/cozo.sqlite"); + if global_db.exists() { + return global_db; + } + } + + // Default: .code_search/cozo.sqlite (will be created if needed) + project_db +} diff --git a/cli/src/commands/accepts/execute.rs b/cli/src/commands/accepts/execute.rs new file mode 100644 index 0000000..ece373c --- /dev/null +++ b/cli/src/commands/accepts/execute.rs @@ -0,0 +1,69 @@ +use std::error::Error; + +use serde::Serialize; + +use super::AcceptsCmd; +use crate::commands::Execute; +use crate::queries::accepts::{find_accepts, AcceptsEntry}; +use crate::types::ModuleGroupResult; + +/// A function's input type information +#[derive(Debug, Clone, Serialize)] +pub struct AcceptsInfo { + pub name: String, + pub arity: i64, + pub inputs: String, + pub return_type: String, + pub line: i64, +} + +impl ModuleGroupResult { + /// Build grouped result from flat AcceptsEntry list + fn from_entries( + pattern: String, + module_filter: Option, + entries: Vec, + ) -> Self { + let total_items = entries.len(); + + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let accepts_info = AcceptsInfo { + name: entry.name, + arity: entry.arity, + inputs: entry.inputs_string, + return_type: entry.return_string, + line: entry.line, + }; + (entry.module, accepts_info) + }); + + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, + } + } +} + +impl Execute for AcceptsCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let entries = find_accepts( + db, + &self.pattern, + &self.common.project, + self.common.regex, + self.module.as_deref(), + self.common.limit, + )?; + + Ok(>::from_entries( + self.pattern, + self.module, + entries, + )) + } +} diff --git a/cli/src/commands/accepts/mod.rs b/cli/src/commands/accepts/mod.rs new file mode 100644 index 0000000..7e7c191 --- /dev/null +++ b/cli/src/commands/accepts/mod.rs @@ -0,0 +1,37 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions accepting a specific type pattern +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search accepts \"User.t\" # Find functions accepting User.t + code_search accepts \"map()\" # Find functions accepting maps + code_search accepts \"User.t\" MyApp # Filter to module MyApp + code_search accepts -r \"list\\(.*\\)\" # Regex pattern matching +")] +pub struct AcceptsCmd { + /// Type pattern to search for in input types + pub pattern: String, + + /// Module filter pattern + pub module: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for AcceptsCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/accepts/output.rs b/cli/src/commands/accepts/output.rs new file mode 100644 index 0000000..9d7e44a --- /dev/null +++ b/cli/src/commands/accepts/output.rs @@ -0,0 +1,33 @@ +//! Output formatting for accepts command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::AcceptsInfo; + +impl TableFormatter for ModuleGroupResult { + type Entry = AcceptsInfo; + + fn format_header(&self) -> String { + let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + format!("Functions accepting \"{}\"", pattern) + } + + fn format_empty_message(&self) -> String { + "No functions found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} function(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, accepts_info: &AcceptsInfo, _module: &str, _file: &str) -> String { + format!( + "{}/{} ({}) → {}", + accepts_info.name, accepts_info.arity, accepts_info.inputs, accepts_info.return_type + ) + } +} diff --git a/cli/src/commands/boundaries/execute.rs b/cli/src/commands/boundaries/execute.rs new file mode 100644 index 0000000..20120a6 --- /dev/null +++ b/cli/src/commands/boundaries/execute.rs @@ -0,0 +1,103 @@ +use std::error::Error; + +use serde::Serialize; + +use super::BoundariesCmd; +use crate::commands::Execute; +use crate::queries::hotspots::{find_hotspots, HotspotKind}; +use crate::types::{ModuleCollectionResult, ModuleGroup}; + +/// A single boundary module entry +#[derive(Debug, Clone, Serialize)] +pub struct BoundaryEntry { + pub incoming: i64, + pub outgoing: i64, + pub ratio: f64, +} + +impl Execute for BoundariesCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let hotspots = find_hotspots( + db, + HotspotKind::Ratio, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.common.limit, + false, + true, // require_outgoing: exclude leaf nodes + )?; + + // Build module groups, filtering by thresholds and deduplicating by module + let mut seen_modules = std::collections::HashSet::new(); + let mut items = Vec::new(); + + for hotspot in hotspots { + // Boundaries must have both incoming AND outgoing calls + // (leaf modules with only incoming calls are not boundaries) + if hotspot.incoming >= self.min_incoming + && hotspot.outgoing >= 1 + && hotspot.ratio >= self.min_ratio + && seen_modules.insert(hotspot.module.clone()) + { + items.push(ModuleGroup { + name: hotspot.module, + file: String::new(), + entries: vec![BoundaryEntry { + incoming: hotspot.incoming, + outgoing: hotspot.outgoing, + ratio: hotspot.ratio, + }], + function_count: None, + }); + } + } + + let total_items = items.len(); + + Ok(ModuleCollectionResult { + module_pattern: self.module.unwrap_or_else(|| "*".to_string()), + function_pattern: None, + kind_filter: Some("boundary".to_string()), + name_filter: None, + total_items, + items, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::fixture; + use tempfile::NamedTempFile; + + #[fixture] + fn test_db() -> NamedTempFile { + NamedTempFile::new().unwrap() + } + + #[test] + fn test_boundaries_execute_creates_result_with_boundary_kind() { + // This test verifies the execute method creates a result with kind_filter set to "boundary" + // Full integration tests would require a real database with call graph data + // For now, we test the structure and defaults + let _cmd = BoundariesCmd { + min_incoming: 5, + min_ratio: 2.0, + module: None, + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 50, + }, + }; + + // The execute method would call find_hotspots and filter results + // We verify the command struct is created correctly + assert_eq!(_cmd.min_incoming, 5); + assert_eq!(_cmd.min_ratio, 2.0); + } +} diff --git a/cli/src/commands/boundaries/mod.rs b/cli/src/commands/boundaries/mod.rs new file mode 100644 index 0000000..7f4e01b --- /dev/null +++ b/cli/src/commands/boundaries/mod.rs @@ -0,0 +1,47 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find boundary modules - modules with high fan-in but low fan-out +/// +/// Boundary modules are those that many other modules depend on but have few +/// dependencies themselves. They are identified by high ratio of incoming to +/// outgoing calls, indicating they are central points in the architecture. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search boundaries # Find all boundary modules + code_search boundaries MyApp.Web # Filter to MyApp.Web namespace + code_search boundaries --min-incoming 5 # With minimum 5 incoming calls + code_search boundaries --min-ratio 2.0 # With minimum 2.0 ratio + code_search boundaries -l 20 # Show top 20 boundary modules +")] +pub struct BoundariesCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Minimum incoming calls to be considered a boundary module + #[arg(long, default_value = "1")] + pub min_incoming: i64, + + /// Minimum ratio (incoming/outgoing) to be considered a boundary module + #[arg(long, default_value = "2.0")] + pub min_ratio: f64, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for BoundariesCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/boundaries/output.rs b/cli/src/commands/boundaries/output.rs new file mode 100644 index 0000000..8dc4139 --- /dev/null +++ b/cli/src/commands/boundaries/output.rs @@ -0,0 +1,79 @@ +//! Output formatting for boundaries command results. + +use super::execute::BoundaryEntry; +use crate::output::TableFormatter; +use crate::types::ModuleCollectionResult; + +impl TableFormatter for ModuleCollectionResult { + type Entry = BoundaryEntry; + + fn format_header(&self) -> String { + let filter_info = if self.module_pattern != "*" { + format!(" (module: {})", self.module_pattern) + } else { + String::new() + }; + format!("Boundary Modules{}", filter_info) + } + + fn format_empty_message(&self) -> String { + "No boundary modules found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} boundary module(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_module_header_with_entries( + &self, + module_name: &str, + _module_file: &str, + entries: &[BoundaryEntry], + ) -> String { + if entries.is_empty() { + return format!("{}:", module_name); + } + + // Get the first (and typically only) entry for module-level stats + let entry = &entries[0]; + + // Format ratio with special case for infinite (outgoing = 0) + let ratio_str = if entry.outgoing == 0 { + "∞".to_string() + } else { + format!("{:.1}", entry.ratio) + }; + + format!( + "{}: (in: {}, out: {}, ratio: {})", + module_name, entry.incoming, entry.outgoing, ratio_str + ) + } + + fn format_entry(&self, entry: &BoundaryEntry, _module: &str, _file: &str) -> String { + // For boundaries, we don't show individual entries since there's only one per module + // But if there are multiple, format them + let ratio_str = if entry.outgoing == 0 { + "∞".to_string() + } else { + format!("{:.1}", entry.ratio) + }; + + format!( + "(in: {}, out: {}, ratio: {})", + entry.incoming, entry.outgoing, ratio_str + ) + } + + fn blank_before_module(&self) -> bool { + true + } + + fn blank_after_summary(&self) -> bool { + false + } +} diff --git a/cli/src/commands/browse_module/cli_tests.rs b/cli/src/commands/browse_module/cli_tests.rs new file mode 100644 index 0000000..fbe1f4b --- /dev/null +++ b/cli/src/commands/browse_module/cli_tests.rs @@ -0,0 +1,115 @@ +//! CLI parsing tests for browse-module command. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use crate::commands::browse_module::DefinitionKind; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + // Positional argument test - browse-module requires a module or file argument + #[test] + fn test_requires_module_or_file() { + let result = Args::try_parse_from(["code_search", "browse-module"]); + assert!(result.is_err(), "Should require module_or_file positional argument"); + } + + crate::cli_option_test! { + command: "browse-module", + variant: BrowseModule, + test_name: test_with_module_name, + args: ["MyApp.Accounts"], + field: module_or_file, + expected: "MyApp.Accounts", + } + + crate::cli_option_test! { + command: "browse-module", + variant: BrowseModule, + test_name: test_with_file_path, + args: ["lib/accounts.ex"], + field: module_or_file, + expected: "lib/accounts.ex", + } + + crate::cli_option_test! { + command: "browse-module", + variant: BrowseModule, + test_name: test_with_regex, + args: ["MyApp.*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "browse-module", + variant: BrowseModule, + test_name: test_with_name_filter, + args: ["MyApp.Accounts", "--name", "get_user"], + field: name, + expected: Some("get_user".to_string()), + } + + crate::cli_option_test! { + command: "browse-module", + variant: BrowseModule, + test_name: test_with_limit, + args: ["MyApp.Accounts", "--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_limit_tests! { + command: "browse-module", + variant: BrowseModule, + required_args: ["MyApp.Accounts"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Kind filter tests (manual - enum variant) + // ========================================================================= + + #[rstest] + #[case("functions", DefinitionKind::Functions)] + #[case("specs", DefinitionKind::Specs)] + #[case("types", DefinitionKind::Types)] + #[case("structs", DefinitionKind::Structs)] + fn test_kind_filter(#[case] kind_str: &str, #[case] expected: DefinitionKind) { + let args = Args::try_parse_from([ + "code_search", + "browse-module", + "MyApp.Accounts", + "--kind", + kind_str, + ]) + .expect("Failed to parse args"); + + if let crate::commands::Command::BrowseModule(cmd) = args.command { + assert!(cmd.kind.is_some()); + assert!(matches!(cmd.kind.unwrap(), k if std::mem::discriminant(&k) == std::mem::discriminant(&expected))); + } else { + panic!("Expected BrowseModule command"); + } + } + + #[test] + fn test_kind_filter_default_is_none() { + let args = Args::try_parse_from(["code_search", "browse-module", "MyApp.Accounts"]) + .expect("Failed to parse args"); + + if let crate::commands::Command::BrowseModule(cmd) = args.command { + assert!(cmd.kind.is_none()); + } else { + panic!("Expected BrowseModule command"); + } + } +} diff --git a/cli/src/commands/browse_module/execute.rs b/cli/src/commands/browse_module/execute.rs new file mode 100644 index 0000000..d239845 --- /dev/null +++ b/cli/src/commands/browse_module/execute.rs @@ -0,0 +1,325 @@ +use std::cmp::Ordering; +use std::error::Error; + +use serde::Serialize; + +use super::{BrowseModuleCmd, DefinitionKind}; +use crate::commands::Execute; +use crate::queries::file::find_functions_in_module; +use crate::queries::specs::find_specs; +use crate::queries::types::find_types; +use crate::queries::structs::{find_struct_fields, group_fields_into_structs, FieldInfo}; + +/// Result of browsing definitions in a module +#[derive(Debug, Serialize)] +pub struct BrowseModuleResult { + /// The module name or file pattern that was searched + pub search_term: String, + + /// The definition kind filter applied (if any) + #[serde(skip_serializing_if = "Option::is_none")] + pub kind_filter: Option, + + /// Project that was searched + pub project: String, + + /// Total number of definitions found (before limit applied) + pub total_items: usize, + + /// All matching definitions, flattened array with type discriminant + pub definitions: Vec, +} + +/// A single definition from any category (function, spec, type, or struct) +/// +/// Uses serde(tag = "type") to add a discriminant field to JSON output, +/// making it easy for consumers to identify the definition type. +#[derive(Debug, Clone, Serialize)] +#[serde(tag = "type")] +#[serde(rename_all = "lowercase")] +pub enum Definition { + /// A function definition with location and signature + Function { + module: String, + #[serde(skip_serializing_if = "String::is_empty")] + file: String, + name: String, + arity: i64, + line: i64, + start_line: i64, + end_line: i64, + kind: String, + #[serde(skip_serializing_if = "String::is_empty")] + args: String, + #[serde(skip_serializing_if = "String::is_empty")] + return_type: String, + #[serde(skip_serializing_if = "String::is_empty")] + pattern: String, + #[serde(skip_serializing_if = "String::is_empty")] + guard: String, + }, + + /// A spec definition (@spec or @callback) + Spec { + module: String, + name: String, + arity: i64, + line: i64, + kind: String, + #[serde(skip_serializing_if = "String::is_empty")] + inputs: String, + #[serde(skip_serializing_if = "String::is_empty")] + returns: String, + #[serde(skip_serializing_if = "String::is_empty")] + full: String, + }, + + /// A type definition (@type, @typep, or @opaque) + Type { + module: String, + name: String, + line: i64, + kind: String, + #[serde(skip_serializing_if = "String::is_empty")] + params: String, + #[serde(skip_serializing_if = "String::is_empty")] + definition: String, + }, + + /// A struct definition with fields + Struct { + module: String, + name: String, + fields: Vec, + }, +} + +impl Definition { + /// Get the module name for this definition + pub fn module(&self) -> &str { + match self { + Definition::Function { module, .. } => module, + Definition::Spec { module, .. } => module, + Definition::Type { module, .. } => module, + Definition::Struct { module, .. } => module, + } + } + + /// Get the line number for this definition + pub fn line(&self) -> i64 { + match self { + Definition::Function { line, .. } => *line, + Definition::Spec { line, .. } => *line, + Definition::Type { line, .. } => *line, + Definition::Struct { .. } => 0, // Structs don't have a single line + } + } +} + +impl Execute for BrowseModuleCmd { + type Output = BrowseModuleResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let mut definitions = Vec::new(); + + // Determine what to query based on kind filter + let should_query_functions = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Functions)); + let should_query_specs = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Specs)); + let should_query_types = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Types)); + let should_query_structs = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Structs)); + + // Query functions (from function_locations table for file + line info) + if should_query_functions { + let funcs = find_functions_in_module( + db, + &self.module_or_file, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + for func in funcs { + // Filter by name if specified + if let Some(ref name_filter) = self.name { + if !func.name.contains(name_filter) { + continue; + } + } + + definitions.push(Definition::Function { + module: func.module, + file: func.file, + name: func.name, + arity: func.arity, + line: func.line, + start_line: func.start_line, + end_line: func.end_line, + kind: func.kind, + args: String::new(), // Not in function_locations + return_type: String::new(), // Not in function_locations + pattern: func.pattern, + guard: func.guard, + }); + } + } + + // Query specs + if should_query_specs { + let specs = find_specs( + db, + &self.module_or_file, + self.name.as_deref(), + None, // kind filter (optional, not used for browse) + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + for spec in specs { + definitions.push(Definition::Spec { + module: spec.module, + name: spec.name, + arity: spec.arity, + line: spec.line, + kind: spec.kind, + inputs: spec.inputs_string, + returns: spec.return_string, + full: spec.full, + }); + } + } + + // Query types + if should_query_types { + let types = find_types( + db, + &self.module_or_file, + self.name.as_deref(), + None, // kind filter (optional, not used for browse) + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + for type_def in types { + definitions.push(Definition::Type { + module: type_def.module, + name: type_def.name, + line: type_def.line, + kind: type_def.kind, + params: type_def.params, + definition: type_def.definition, + }); + } + } + + // Query structs + if should_query_structs { + let fields = find_struct_fields(db, &self.module_or_file, &self.common.project, self.common.regex, self.common.limit)?; + let structs = group_fields_into_structs(fields); + + for struct_def in structs { + // Filter by name if specified + if let Some(ref name_filter) = self.name { + if !struct_def.module.contains(name_filter) { + continue; + } + } + + definitions.push(Definition::Struct { + module: struct_def.module.clone(), + name: struct_def.module.clone(), // Struct name is same as module for now + fields: struct_def.fields, + }); + } + } + + // Sort by module, then by line number + definitions.sort_by(|a, b| { + match a.module().cmp(b.module()) { + Ordering::Equal => a.line().cmp(&b.line()), + other => other, + } + }); + + let total_items = definitions.len(); + + // Apply limit + definitions.truncate(self.common.limit as usize); + + Ok(BrowseModuleResult { + search_term: self.module_or_file, + kind_filter: self.kind, + project: self.common.project, + total_items, + definitions, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_definition_sort_order() { + let defs = vec![ + Definition::Function { + module: "B".to_string(), + file: String::new(), + name: "f".to_string(), + arity: 0, + line: 10, + start_line: 10, + end_line: 10, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + Definition::Function { + module: "A".to_string(), + file: String::new(), + name: "f".to_string(), + arity: 0, + line: 20, + start_line: 20, + end_line: 20, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + Definition::Function { + module: "A".to_string(), + file: String::new(), + name: "f".to_string(), + arity: 0, + line: 5, + start_line: 5, + end_line: 5, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + ]; + + let mut sorted = defs.clone(); + sorted.sort_by(|a, b| match a.module().cmp(b.module()) { + Ordering::Equal => a.line().cmp(&b.line()), + other => other, + }); + + // Should be: A/5, A/20, B/10 + assert_eq!(sorted[0].module(), "A"); + assert_eq!(sorted[0].line(), 5); + assert_eq!(sorted[1].module(), "A"); + assert_eq!(sorted[1].line(), 20); + assert_eq!(sorted[2].module(), "B"); + assert_eq!(sorted[2].line(), 10); + } +} diff --git a/cli/src/commands/browse_module/execute_tests.rs b/cli/src/commands/browse_module/execute_tests.rs new file mode 100644 index 0000000..61041db --- /dev/null +++ b/cli/src/commands/browse_module/execute_tests.rs @@ -0,0 +1,323 @@ +//! Execute tests for browse-module command. + +#[cfg(test)] +mod tests { + use super::super::{BrowseModuleCmd, DefinitionKind}; + use super::super::execute::Definition; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Fixtures - call_graph has functions, specs, and types + // ========================================================================= + + crate::shared_fixture! { + fixture_name: call_graph_db, + fixture_type: call_graph, + project: "test_project", + } + + crate::shared_fixture! { + fixture_name: structs_db, + fixture_type: structs, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests - Functions + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_finds_functions, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: Some(DefinitionKind::Functions), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(!result.definitions.is_empty()); + // All definitions should be functions + for def in &result.definitions { + assert!(matches!(def, Definition::Function { .. })); + } + // MyApp.Accounts has: get_user/1, get_user/2, list_users/0, validate_email/1 + assert_eq!(result.definitions.len(), 4); + }, + } + + crate::execute_test! { + test_name: test_browse_module_with_name_filter, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: Some(DefinitionKind::Functions), + name: Some("get_user".to_string()), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // Only get_user/1 and get_user/2 should match + assert_eq!(result.definitions.len(), 2); + for def in &result.definitions { + if let Definition::Function { name, .. } = def { + assert!(name.contains("get_user")); + } + } + }, + } + + // ========================================================================= + // Core functionality tests - Specs + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_finds_specs, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: Some(DefinitionKind::Specs), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(!result.definitions.is_empty()); + // All definitions should be specs + for def in &result.definitions { + assert!(matches!(def, Definition::Spec { .. })); + } + // MyApp.Accounts has specs for: get_user/1, list_users/0 + assert_eq!(result.definitions.len(), 2); + }, + } + + // ========================================================================= + // Core functionality tests - Types + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_finds_types, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: Some(DefinitionKind::Types), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(!result.definitions.is_empty()); + // All definitions should be types + for def in &result.definitions { + assert!(matches!(def, Definition::Type { .. })); + } + // MyApp.Accounts has types: user (type), user_id (opaque) + assert_eq!(result.definitions.len(), 2); + }, + } + + // ========================================================================= + // Core functionality tests - Structs + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_finds_structs, + fixture: structs_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.User".to_string(), + kind: Some(DefinitionKind::Structs), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.definitions.len(), 1); + if let Definition::Struct { name, fields, .. } = &result.definitions[0] { + assert_eq!(name, "MyApp.User"); + // User has: id, name, email, admin, inserted_at + assert_eq!(fields.len(), 5); + } else { + panic!("Expected struct definition"); + } + }, + } + + // ========================================================================= + // Core functionality tests - All kinds (no filter) + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_all_kinds, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: None, // No kind filter - get all + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // Should have functions, specs, and types + let has_functions = result.definitions.iter().any(|d| matches!(d, Definition::Function { .. })); + let has_specs = result.definitions.iter().any(|d| matches!(d, Definition::Spec { .. })); + let has_types = result.definitions.iter().any(|d| matches!(d, Definition::Type { .. })); + + assert!(has_functions, "Should have functions"); + assert!(has_specs, "Should have specs"); + assert!(has_types, "Should have types"); + + // Functions: 4, Specs: 2, Types: 2 = 8 total + assert_eq!(result.total_items, 8); + }, + } + + // ========================================================================= + // Regex pattern tests + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_regex_pattern, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp\\..*".to_string(), + kind: Some(DefinitionKind::Functions), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + // Should find functions from all MyApp.* modules + assert!(!result.definitions.is_empty()); + // Total functions across all modules in fixture: + // Controller: 3, Accounts: 4, Service: 3, Repo: 3, Notifier: 2 = 15 + assert_eq!(result.definitions.len(), 15); + }, + } + + // ========================================================================= + // Sort order tests + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_sorted_by_module_then_line, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp\\..*".to_string(), + kind: Some(DefinitionKind::Functions), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + // Verify sorted by module then by line + let mut prev_module = String::new(); + let mut prev_line: i64 = 0; + + for def in &result.definitions { + let (module, line) = match def { + Definition::Function { module, line, .. } => (module.clone(), *line), + _ => continue, + }; + + if module == prev_module { + assert!(line >= prev_line, "Within same module, lines should be ascending"); + } else if !prev_module.is_empty() { + assert!(module >= prev_module, "Modules should be in alphabetical order"); + } + + prev_module = module; + prev_line = line; + } + }, + } + + // ========================================================================= + // Limit tests + // ========================================================================= + + crate::execute_test! { + test_name: test_browse_module_with_limit, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "MyApp\\..*".to_string(), + kind: Some(DefinitionKind::Functions), + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 5, + }, + }, + assertions: |result| { + // Should respect limit + assert_eq!(result.definitions.len(), 5); + // total_items should reflect actual count before limit + assert!(result.total_items >= 5); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_browse_module_no_match, + fixture: call_graph_db, + cmd: BrowseModuleCmd { + module_or_file: "NonExistent.Module".to_string(), + kind: None, + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: definitions, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: BrowseModuleCmd, + cmd: BrowseModuleCmd { + module_or_file: "MyApp.Accounts".to_string(), + kind: None, + name: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/browse_module/mod.rs b/cli/src/commands/browse_module/mod.rs new file mode 100644 index 0000000..791f378 --- /dev/null +++ b/cli/src/commands/browse_module/mod.rs @@ -0,0 +1,79 @@ +use std::error::Error; + +use clap::{Parser, ValueEnum}; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; +use serde::Serialize; + +mod cli_tests; +pub mod execute; +mod execute_tests; +pub mod output; +mod output_tests; + +/// Browse definitions in a module or file +/// +/// Unified command to explore all definitions (functions, specs, types, structs) +/// in a given module or file pattern. Returns all matching definitions grouped +/// and sorted by module and line number. +#[derive(Parser, Debug)] +pub struct BrowseModuleCmd { + /// Module name, pattern, or file path to browse + /// + /// Can be: + /// - Module name: "MyApp.Accounts" (exact match or pattern) + /// - File path: "lib/accounts.ex" (substring or regex with --regex) + /// - Pattern: "MyApp.*" (with --regex) + pub module_or_file: String, + + /// Type of definitions to show + /// + /// If omitted, shows all definition types (functions, specs, types, structs). + /// If specified, filters to only that type. + #[arg(short, long)] + pub kind: Option, + + /// Filter by definition name (function/type/spec/struct name) + /// + /// Applies across all definition types. Supports substring match by default + /// or regex match with --regex. + #[arg(short, long)] + pub name: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +/// Type of definition to filter by +#[derive(Debug, Clone, Copy, ValueEnum, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum DefinitionKind { + /// Function definitions + Functions, + /// @spec and @callback definitions + Specs, + /// @type, @typep, @opaque definitions + Types, + /// Struct definitions with fields + Structs, +} + +impl std::fmt::Display for DefinitionKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DefinitionKind::Functions => write!(f, "functions"), + DefinitionKind::Specs => write!(f, "specs"), + DefinitionKind::Types => write!(f, "types"), + DefinitionKind::Structs => write!(f, "structs"), + } + } +} + +impl CommandRunner for BrowseModuleCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/browse_module/output.rs b/cli/src/commands/browse_module/output.rs new file mode 100644 index 0000000..869a53b --- /dev/null +++ b/cli/src/commands/browse_module/output.rs @@ -0,0 +1,215 @@ +use std::collections::BTreeMap; + +use super::execute::{BrowseModuleResult, Definition}; +use crate::output::Outputable; +use crate::utils::format_type_definition; + +impl Outputable for BrowseModuleResult { + fn to_table(&self) -> String { + let mut output = String::new(); + + // Header + if let Some(kind) = self.kind_filter { + output.push_str(&format!( + "Definitions in {} (kind: {}, project: {})\n\n", + self.search_term, kind, self.project + )); + } else { + output.push_str(&format!( + "Definitions in {} (project: {})\n\n", + self.search_term, self.project + )); + } + + // Empty state + if self.definitions.is_empty() { + output.push_str("No definitions found.\n"); + return output; + } + + // Summary + output.push_str(&format!( + "Found {} definition(s):\n\n", + self.total_items + )); + + // Group by module for readability + let mut by_module: BTreeMap> = BTreeMap::new(); + for def in &self.definitions { + by_module + .entry(def.module().to_string()) + .or_insert_with(Vec::new) + .push(def); + } + + // Format each module and its definitions + for (module, definitions) in by_module { + output.push_str(&format!(" {}:\n", module)); + + for def in definitions { + match def { + Definition::Function { + name, + arity, + start_line, + end_line, + kind, + args, + return_type, + .. + } => { + output.push_str(&format!(" L{}-{} [{}] {}/{}\n", start_line, end_line, kind, name, arity)); + if !args.is_empty() || !return_type.is_empty() { + output.push_str(&format!(" {} {}\n", args, return_type).trim_end()); + output.push('\n'); + } + } + + Definition::Spec { + name, + arity, + line, + kind, + full, + .. + } => { + output.push_str(&format!(" L{:<3} [{}] {}/{}\n", line, kind, name, arity)); + if !full.is_empty() { + output.push_str(&format!(" {}\n", full)); + } + } + + Definition::Type { + name, + line, + kind, + definition, + .. + } => { + output.push_str(&format!(" L{:<3} [{}] {}\n", line, kind, name)); + if !definition.is_empty() { + let formatted = format_type_definition(definition); + // Indent multi-line definitions properly + for (i, def_line) in formatted.lines().enumerate() { + if i == 0 { + output.push_str(&format!(" {}\n", def_line)); + } else { + output.push_str(&format!(" {}\n", def_line)); + } + } + } + } + + Definition::Struct { name, fields, .. } => { + output.push_str(&format!(" [struct] {} with {} fields\n", name, fields.len())); + for field in fields.iter() { + output.push_str(&format!( + " - {}: {} {}\n", + field.name, + field.inferred_type, + if field.required { "(required)" } else { "(optional)" } + )); + } + } + } + } + + output.push('\n'); + } + + output + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_empty_result() { + let result = BrowseModuleResult { + search_term: "NonExistent".to_string(), + kind_filter: None, + project: "default".to_string(), + total_items: 0, + definitions: vec![], + }; + + let table = result.to_table(); + assert!(table.contains("No definitions found")); + } + + #[test] + fn test_function_formatting() { + use super::super::execute::Definition; + + let result = BrowseModuleResult { + search_term: "MyApp.Accounts".to_string(), + kind_filter: None, + project: "default".to_string(), + total_items: 1, + definitions: vec![Definition::Function { + module: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + name: "get_user".to_string(), + arity: 1, + line: 10, + start_line: 10, + end_line: 20, + kind: "def".to_string(), + args: "(integer())".to_string(), + return_type: "User.t() | nil".to_string(), + pattern: String::new(), + guard: String::new(), + }], + }; + + let table = result.to_table(); + assert!(table.contains("MyApp.Accounts")); + assert!(table.contains("get_user/1")); + assert!(table.contains("[def]")); + assert!(table.contains("L10-20")); + } + + #[test] + fn test_mixed_types_formatting() { + use super::super::execute::Definition; + + let result = BrowseModuleResult { + search_term: "MyApp.Accounts".to_string(), + kind_filter: None, + project: "default".to_string(), + total_items: 2, + definitions: vec![ + Definition::Function { + module: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + name: "get_user".to_string(), + arity: 1, + line: 10, + start_line: 10, + end_line: 20, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + Definition::Type { + module: "MyApp.Accounts".to_string(), + name: "user".to_string(), + line: 5, + kind: "type".to_string(), + params: String::new(), + definition: "@type user() :: %{}".to_string(), + }, + ], + }; + + let table = result.to_table(); + assert!(table.contains("MyApp.Accounts")); + assert!(table.contains("[def]")); + assert!(table.contains("[type]")); + assert!(table.contains("Found 2 definition(s)")); + } +} diff --git a/cli/src/commands/browse_module/output_tests.rs b/cli/src/commands/browse_module/output_tests.rs new file mode 100644 index 0000000..2790b4a --- /dev/null +++ b/cli/src/commands/browse_module/output_tests.rs @@ -0,0 +1,261 @@ +//! Output formatting tests for browse-module command. + +#[cfg(test)] +mod tests { + use super::super::execute::{BrowseModuleResult, Definition}; + use super::super::DefinitionKind; + use crate::queries::structs::FieldInfo; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Definitions in NonExistent (project: default) + +No definitions found. +"; + + const FUNCTIONS_ONLY_TABLE: &str = "\ +Definitions in MyApp.Accounts (kind: functions, project: default) + +Found 2 definition(s): + + MyApp.Accounts: + L10-15 [def] get_user/1 + L24-28 [def] list_users/0 + +"; + + const MIXED_TYPES_TABLE: &str = "\ +Definitions in MyApp.Accounts (project: default) + +Found 3 definition(s): + + MyApp.Accounts: + L5 [type] user + @type user() :: %{id: integer()} + L8 [spec] get_user/1 + @spec get_user(integer()) :: User.t() + L10-15 [def] get_user/1 + +"; + + const STRUCT_TABLE: &str = "\ +Definitions in MyApp.User (kind: structs, project: default) + +Found 1 definition(s): + + MyApp.User: + [struct] MyApp.User with 2 fields + - id: integer() (required) + - name: String.t() (optional) + +"; + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> BrowseModuleResult { + BrowseModuleResult { + search_term: "NonExistent".to_string(), + kind_filter: None, + project: "default".to_string(), + total_items: 0, + definitions: vec![], + } + } + + #[fixture] + fn functions_only_result() -> BrowseModuleResult { + BrowseModuleResult { + search_term: "MyApp.Accounts".to_string(), + kind_filter: Some(DefinitionKind::Functions), + project: "default".to_string(), + total_items: 2, + definitions: vec![ + Definition::Function { + module: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + name: "get_user".to_string(), + arity: 1, + line: 10, + start_line: 10, + end_line: 15, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + Definition::Function { + module: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + name: "list_users".to_string(), + arity: 0, + line: 24, + start_line: 24, + end_line: 28, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + ], + } + } + + #[fixture] + fn mixed_types_result() -> BrowseModuleResult { + // Definitions are sorted by module then line - so L5, L8, L10 + BrowseModuleResult { + search_term: "MyApp.Accounts".to_string(), + kind_filter: None, + project: "default".to_string(), + total_items: 3, + definitions: vec![ + Definition::Type { + module: "MyApp.Accounts".to_string(), + name: "user".to_string(), + line: 5, + kind: "type".to_string(), + params: String::new(), + definition: "@type user() :: %{id: integer()}".to_string(), + }, + Definition::Spec { + module: "MyApp.Accounts".to_string(), + name: "get_user".to_string(), + arity: 1, + line: 8, + kind: "spec".to_string(), + inputs: "integer()".to_string(), + returns: "User.t()".to_string(), + full: "@spec get_user(integer()) :: User.t()".to_string(), + }, + Definition::Function { + module: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + name: "get_user".to_string(), + arity: 1, + line: 10, + start_line: 10, + end_line: 15, + kind: "def".to_string(), + args: String::new(), + return_type: String::new(), + pattern: String::new(), + guard: String::new(), + }, + ], + } + } + + #[fixture] + fn struct_result() -> BrowseModuleResult { + BrowseModuleResult { + search_term: "MyApp.User".to_string(), + kind_filter: Some(DefinitionKind::Structs), + project: "default".to_string(), + total_items: 1, + definitions: vec![Definition::Struct { + module: "MyApp.User".to_string(), + name: "MyApp.User".to_string(), + fields: vec![ + FieldInfo { + name: "id".to_string(), + inferred_type: "integer()".to_string(), + default_value: "nil".to_string(), + required: true, + }, + FieldInfo { + name: "name".to_string(), + inferred_type: "String.t()".to_string(), + default_value: "nil".to_string(), + required: false, + }, + ], + }], + } + } + + // ========================================================================= + // Table format tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: BrowseModuleResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_functions_only, + fixture: functions_only_result, + fixture_type: BrowseModuleResult, + expected: FUNCTIONS_ONLY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_mixed_types, + fixture: mixed_types_result, + fixture_type: BrowseModuleResult, + expected: MIXED_TYPES_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_struct, + fixture: struct_result, + fixture_type: BrowseModuleResult, + expected: STRUCT_TABLE, + } + + // ========================================================================= + // JSON format tests + // ========================================================================= + + #[rstest] + fn test_json_format_contains_type_discriminant(functions_only_result: BrowseModuleResult) { + use crate::output::{OutputFormat, Outputable}; + + let json = functions_only_result.format(OutputFormat::Json); + + // Verify the type tag is present for each definition + assert!(json.contains("\"type\": \"function\"")); + } + + #[rstest] + fn test_json_format_struct_contains_fields(struct_result: BrowseModuleResult) { + use crate::output::{OutputFormat, Outputable}; + + let json = struct_result.format(OutputFormat::Json); + + assert!(json.contains("\"type\": \"struct\"")); + assert!(json.contains("\"fields\"")); + assert!(json.contains("\"id\"")); + assert!(json.contains("\"name\"")); + } + + // ========================================================================= + // Toon format tests + // ========================================================================= + + #[rstest] + fn test_toon_format_compact(functions_only_result: BrowseModuleResult) { + use crate::output::{OutputFormat, Outputable}; + + let toon = functions_only_result.format(OutputFormat::Toon); + + // Toon format should be more compact than JSON + let json = functions_only_result.format(OutputFormat::Json); + assert!(toon.len() < json.len(), "Toon should be more compact than JSON"); + + // Should contain key information + assert!(toon.contains("MyApp.Accounts")); + assert!(toon.contains("get_user")); + } +} diff --git a/cli/src/commands/calls_from/cli_tests.rs b/cli/src/commands/calls_from/cli_tests.rs new file mode 100644 index 0000000..bda1917 --- /dev/null +++ b/cli/src/commands/calls_from/cli_tests.rs @@ -0,0 +1,74 @@ +//! CLI parsing tests for calls-from command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_required_arg_test! { + command: "calls-from", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_option_test! { + command: "calls-from", + variant: CallsFrom, + test_name: test_with_module, + args: ["MyApp.Accounts"], + field: module, + expected: "MyApp.Accounts", + } + + crate::cli_option_test! { + command: "calls-from", + variant: CallsFrom, + test_name: test_with_function, + args: ["MyApp.Accounts", "get_user"], + field: function, + expected: Some("get_user".to_string()), + } + + crate::cli_option_test! { + command: "calls-from", + variant: CallsFrom, + test_name: test_with_arity, + args: ["MyApp.Accounts", "get_user", "1"], + field: arity, + expected: Some(1), + } + + crate::cli_option_test! { + command: "calls-from", + variant: CallsFrom, + test_name: test_with_regex, + args: ["MyApp.*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "calls-from", + variant: CallsFrom, + test_name: test_with_limit, + args: ["MyApp.Accounts", "--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_limit_tests! { + command: "calls-from", + variant: CallsFrom, + required_args: ["MyApp.Accounts"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/calls_from/execute.rs b/cli/src/commands/calls_from/execute.rs new file mode 100644 index 0000000..873afb9 --- /dev/null +++ b/cli/src/commands/calls_from/execute.rs @@ -0,0 +1,101 @@ +use std::error::Error; + +use serde::Serialize; + +use super::CallsFromCmd; +use crate::commands::Execute; +use crate::queries::calls_from::find_calls_from; +use crate::types::{Call, ModuleGroupResult}; +use crate::utils::group_calls; + +/// A caller function with all its outgoing calls +#[derive(Debug, Clone, Serialize)] +pub struct CallerFunction { + pub name: String, + pub arity: i64, + pub kind: String, + pub start_line: i64, + pub end_line: i64, + pub calls: Vec, +} + +impl ModuleGroupResult { + /// Build grouped result from flat calls + pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { + let (total_items, items) = group_calls( + calls, + // Group by caller module + |call| call.caller.module.to_string(), + // Key by caller function metadata + |call| CallerFunctionKey { + name: call.caller.name.to_string(), + arity: call.caller.arity, + kind: call.caller.kind.as_deref().unwrap_or("").to_string(), + start_line: call.caller.start_line.unwrap_or(0), + end_line: call.caller.end_line.unwrap_or(0), + }, + // Sort by line number + |a, b| a.line.cmp(&b.line), + // Deduplicate by callee (module, name, arity) + |c| (c.callee.module.to_string(), c.callee.name.to_string(), c.callee.arity), + // Build CallerFunction entry + |key, calls| CallerFunction { + name: key.name, + arity: key.arity, + kind: key.kind, + start_line: key.start_line, + end_line: key.end_line, + calls, + }, + // File tracking strategy: extract from first call in first function + |_module, functions_map| { + functions_map + .values() + .next() + .and_then(|calls| calls.first()) + .and_then(|call| call.caller.file.as_deref()) + .unwrap_or("") + .to_string() + }, + ); + + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, + } + } +} + +/// Key for grouping by caller function (used internally) +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct CallerFunctionKey { + name: String, + arity: i64, + kind: String, + start_line: i64, + end_line: i64, +} + +impl Execute for CallsFromCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let calls = find_calls_from( + db, + &self.module, + self.function.as_deref(), + self.arity, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(>::from_calls( + self.module, + self.function.unwrap_or_default(), + calls, + )) + } +} diff --git a/cli/src/commands/calls_from/execute_tests.rs b/cli/src/commands/calls_from/execute_tests.rs new file mode 100644 index 0000000..cda895b --- /dev/null +++ b/cli/src/commands/calls_from/execute_tests.rs @@ -0,0 +1,172 @@ +//! Execute tests for calls-from command. + +#[cfg(test)] +mod tests { + use super::super::CallsFromCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // MyApp.Accounts has 3 call records: get_user/1→Repo.get, get_user/2→Repo.get, list_users→Repo.all + // Per-function deduplication: each function keeps its unique callees = 3 calls displayed + crate::execute_test! { + test_name: test_calls_from_module, + fixture: populated_db, + cmd: CallsFromCmd { + module: "MyApp.Accounts".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3, + "Expected 3 displayed calls from MyApp.Accounts (1 per caller function)"); + }, + } + + // get_user functions (both arities) call Repo.get + // Per-function deduplication: get_user/1 has 1 call, get_user/2 has 1 call = 2 displayed + crate::execute_test! { + test_name: test_calls_from_function, + fixture: populated_db, + cmd: CallsFromCmd { + module: "MyApp.Accounts".to_string(), + function: Some("get_user".to_string()), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2, + "Expected 2 displayed calls (1 from each get_user arity)"); + // Check that all calls target MyApp.Repo.get + for module in &result.items { + for func in &module.entries { + for call in &func.calls { + assert_eq!(call.callee.module.as_ref(), "MyApp.Repo"); + assert_eq!(call.callee.name.as_ref(), "get"); + } + } + } + }, + } + + // All 11 calls in the fixture are from MyApp.* modules + // Per-function deduplication: each caller keeps unique callees = 11 displayed + crate::execute_test! { + test_name: test_calls_from_regex_module, + fixture: populated_db, + cmd: CallsFromCmd { + module: "MyApp\\..*".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 11, + "Expected 11 displayed calls from MyApp.* modules"); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_test! { + test_name: test_calls_from_no_match, + fixture: populated_db, + cmd: CallsFromCmd { + module: "NonExistent".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(result.items.is_empty(), "Expected no modules for non-existent module"); + assert_eq!(result.total_items, 0); + }, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_calls_from_with_project_filter, + fixture: populated_db, + cmd: CallsFromCmd { + module: "MyApp.Accounts".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // All results should be for the test_project (verified implicitly by getting results) + assert!(result.total_items > 0, "Should have calls with project filter"); + }, + } + + crate::execute_test! { + test_name: test_calls_from_with_limit, + fixture: populated_db, + cmd: CallsFromCmd { + module: "MyApp\\..*".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 1, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 1, "Limit should restrict to 1 call"); + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: CallsFromCmd, + cmd: CallsFromCmd { + module: "MyApp".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/calls_from/mod.rs b/cli/src/commands/calls_from/mod.rs new file mode 100644 index 0000000..f0713b7 --- /dev/null +++ b/cli/src/commands/calls_from/mod.rs @@ -0,0 +1,41 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Show what a module/function calls (outgoing edges) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search calls-from MyApp.Accounts # All calls from module + code_search calls-from MyApp.Accounts get_user # Calls from specific function + code_search calls-from MyApp.Accounts get_user 1 # With specific arity")] +pub struct CallsFromCmd { + /// Module name (exact match or pattern with --regex) + pub module: String, + + /// Function name (optional, if not specified shows all calls from module) + pub function: Option, + + /// Function arity (optional, matches all arities if not specified) + pub arity: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for CallsFromCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/calls_from/output.rs b/cli/src/commands/calls_from/output.rs new file mode 100644 index 0000000..d0dac92 --- /dev/null +++ b/cli/src/commands/calls_from/output.rs @@ -0,0 +1,48 @@ +//! Output formatting for calls-from command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::CallerFunction; + +impl TableFormatter for ModuleGroupResult { + type Entry = CallerFunction; + + fn format_header(&self) -> String { + if self.function_pattern.is_none() || self.function_pattern.as_ref().unwrap().is_empty() { + format!("Calls from: {}", self.module_pattern) + } else { + format!("Calls from: {}.{}", self.module_pattern, self.function_pattern.as_ref().unwrap()) + } + } + + fn format_empty_message(&self) -> String { + "No calls found.".to_string() + } + + fn format_summary(&self, total: usize, _module_count: usize) -> String { + format!("Found {} call(s):", total) + } + + fn format_module_header(&self, module_name: &str, module_file: &str) -> String { + format!("{} ({})", module_name, module_file) + } + + fn format_entry(&self, func: &CallerFunction, _module: &str, _file: &str) -> String { + let kind_str = if func.kind.is_empty() { + String::new() + } else { + format!(" [{}]", func.kind) + }; + format!( + "{}/{} ({}:{}){}", + func.name, func.arity, func.start_line, func.end_line, kind_str + ) + } + + fn format_entry_details(&self, func: &CallerFunction, module: &str, file: &str) -> Vec { + func.calls + .iter() + .map(|call| call.format_outgoing(module, file)) + .collect() + } +} diff --git a/cli/src/commands/calls_from/output_tests.rs b/cli/src/commands/calls_from/output_tests.rs new file mode 100644 index 0000000..cd77a74 --- /dev/null +++ b/cli/src/commands/calls_from/output_tests.rs @@ -0,0 +1,162 @@ +//! Output formatting tests for calls-from command. + +#[cfg(test)] +mod tests { + use super::super::execute::CallerFunction; + use crate::types::{Call, FunctionRef, ModuleGroupResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Calls from: MyApp.Accounts.get_user + +No calls found."; + + const SINGLE_TABLE: &str = "\ +Calls from: MyApp.Accounts.get_user + +Found 1 call(s): + +MyApp.Accounts (lib/my_app/accounts.ex) + get_user/1 (10:15) + → @ L12 MyApp.Repo.get/2"; + + const MULTIPLE_TABLE: &str = "\ +Calls from: MyApp.Accounts + +Found 2 call(s): + +MyApp.Accounts (lib/my_app/accounts.ex) + get_user/1 (10:15) + → @ L12 MyApp.Repo.get/2 + list_users/0 (20:25) + → @ L22 MyApp.Repo.all/1"; + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Accounts".to_string(), + "get_user".to_string(), + vec![], + ) + } + + #[fixture] + fn single_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Accounts".to_string(), + "get_user".to_string(), + vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "get_user", + 1, + "", + "lib/my_app/accounts.ex", + 10, + 15, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 12, + call_type: Some("remote".to_string()), + depth: None, + }], + ) + } + + #[fixture] + fn multiple_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Accounts".to_string(), + String::new(), + vec![ + Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "get_user", + 1, + "", + "lib/my_app/accounts.ex", + 10, + 15, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 12, + call_type: Some("remote".to_string()), + depth: None, + }, + Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "list_users", + 0, + "", + "lib/my_app/accounts.ex", + 20, + 25, + ), + callee: FunctionRef::new("MyApp.Repo", "all", 1), + line: 22, + call_type: Some("remote".to_string()), + depth: None, + }, + ], + ) + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: ModuleGroupResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_from", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_from", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_from", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/calls_to/cli_tests.rs b/cli/src/commands/calls_to/cli_tests.rs new file mode 100644 index 0000000..0adf137 --- /dev/null +++ b/cli/src/commands/calls_to/cli_tests.rs @@ -0,0 +1,74 @@ +//! CLI parsing tests for calls-to command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_required_arg_test! { + command: "calls-to", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_option_test! { + command: "calls-to", + variant: CallsTo, + test_name: test_with_module, + args: ["MyApp.Repo"], + field: module, + expected: "MyApp.Repo", + } + + crate::cli_option_test! { + command: "calls-to", + variant: CallsTo, + test_name: test_with_function, + args: ["MyApp.Repo", "get"], + field: function, + expected: Some("get".to_string()), + } + + crate::cli_option_test! { + command: "calls-to", + variant: CallsTo, + test_name: test_with_arity, + args: ["MyApp.Repo", "get", "2"], + field: arity, + expected: Some(2), + } + + crate::cli_option_test! { + command: "calls-to", + variant: CallsTo, + test_name: test_with_regex, + args: ["MyApp\\.Repo", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "calls-to", + variant: CallsTo, + test_name: test_with_limit, + args: ["MyApp.Repo", "--limit", "25"], + field: common.limit, + expected: 25, + } + + crate::cli_limit_tests! { + command: "calls-to", + variant: CallsTo, + required_args: ["MyApp.Repo"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/calls_to/execute.rs b/cli/src/commands/calls_to/execute.rs new file mode 100644 index 0000000..866d574 --- /dev/null +++ b/cli/src/commands/calls_to/execute.rs @@ -0,0 +1,88 @@ +use std::error::Error; + +use serde::Serialize; + +use super::CallsToCmd; +use crate::commands::Execute; +use crate::queries::calls_to::find_calls_to; +use crate::types::{Call, ModuleGroupResult}; +use crate::utils::group_calls; + +/// A callee function (target) with all its callers +#[derive(Debug, Clone, Serialize)] +pub struct CalleeFunction { + pub name: String, + pub arity: i64, + pub callers: Vec, +} + +impl ModuleGroupResult { + /// Build grouped result from flat calls + pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { + let (total_items, items) = group_calls( + calls, + // Group by callee module + |call| call.callee.module.to_string(), + // Key by callee function metadata + |call| CalleeFunctionKey { + name: call.callee.name.to_string(), + arity: call.callee.arity, + }, + // Sort by caller module, name, arity, then line + |a, b| { + a.caller.module.as_ref().cmp(b.caller.module.as_ref()) + .then_with(|| a.caller.name.as_ref().cmp(b.caller.name.as_ref())) + .then_with(|| a.caller.arity.cmp(&b.caller.arity)) + .then_with(|| a.line.cmp(&b.line)) + }, + // Deduplicate by caller (module, name, arity) + |c| (c.caller.module.to_string(), c.caller.name.to_string(), c.caller.arity), + // Build CalleeFunction entry + |key, callers| CalleeFunction { + name: key.name, + arity: key.arity, + callers, + }, + // File is intentionally empty because callees are the grouping key, + // and a module can be defined across multiple files. The calls themselves + // carry file information where needed. + |_module, _map| String::new(), + ); + + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, + } + } +} + +/// Key for grouping by callee function +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct CalleeFunctionKey { + name: String, + arity: i64, +} + +impl Execute for CallsToCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let calls = find_calls_to( + db, + &self.module, + self.function.as_deref(), + self.arity, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(>::from_calls( + self.module, + self.function.unwrap_or_default(), + calls, + )) + } +} diff --git a/cli/src/commands/calls_to/execute_tests.rs b/cli/src/commands/calls_to/execute_tests.rs new file mode 100644 index 0000000..e86d94e --- /dev/null +++ b/cli/src/commands/calls_to/execute_tests.rs @@ -0,0 +1,202 @@ +//! Execute tests for calls-to command. + +#[cfg(test)] +mod tests { + use super::super::CallsToCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // 4 calls to MyApp.Repo: get_user/1→get, get_user/2→get, list_users→all, do_fetch→get + crate::execute_test! { + test_name: test_calls_to_module, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 4, + "Expected 4 total calls to MyApp.Repo"); + }, + } + + // 3 calls to Repo.get: from get_user/1, get_user/2, do_fetch + crate::execute_test! { + test_name: test_calls_to_function, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: Some("get".to_string()), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3, + "Expected 3 calls to MyApp.Repo.get"); + }, + } + + crate::execute_test! { + test_name: test_calls_to_function_with_arity, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: Some("get".to_string()), + arity: Some(2), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3); + // All callee functions should be get/2 + for module in &result.items { + for func in &module.entries { + assert_eq!(func.arity, 2); + } + } + }, + } + + // 4 calls match get|all: 3 to get + 1 to all + crate::execute_test! { + test_name: test_calls_to_regex_function, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: Some("get|all".to_string()), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 4, + "Expected 4 calls to get|all"); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_test! { + test_name: test_calls_to_no_match, + fixture: populated_db, + cmd: CallsToCmd { + module: "NonExistent".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(result.items.is_empty(), "Expected no modules for non-existent target"); + assert_eq!(result.total_items, 0); + }, + } + + crate::execute_test! { + test_name: test_calls_to_nonexistent_arity, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: Some("get".to_string()), + arity: Some(99), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(result.items.is_empty(), "Expected no results for non-existent arity"); + assert_eq!(result.total_items, 0); + }, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_calls_to_with_project_filter, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert!(result.total_items > 0, "Should have calls with project filter"); + }, + } + + crate::execute_test! { + test_name: test_calls_to_with_limit, + fixture: populated_db, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 2, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2, "Limit should restrict to 2 calls"); + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: CallsToCmd, + cmd: CallsToCmd { + module: "MyApp.Repo".to_string(), + function: None, + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/calls_to/mod.rs b/cli/src/commands/calls_to/mod.rs new file mode 100644 index 0000000..f4d13d0 --- /dev/null +++ b/cli/src/commands/calls_to/mod.rs @@ -0,0 +1,42 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Show what calls a module/function (incoming edges) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search calls-to MyApp.Repo # All callers of module + code_search calls-to MyApp.Repo get # Callers of specific function + code_search calls-to MyApp.Repo get 2 # With specific arity + code_search calls-to MyApp.Accounts get_user # Find all call sites")] +pub struct CallsToCmd { + /// Module name (exact match or pattern with --regex) + pub module: String, + + /// Function name (optional, if not specified shows all calls to module) + pub function: Option, + + /// Function arity (optional, matches all arities if not specified) + pub arity: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for CallsToCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/calls_to/output.rs b/cli/src/commands/calls_to/output.rs new file mode 100644 index 0000000..2bdbc3d --- /dev/null +++ b/cli/src/commands/calls_to/output.rs @@ -0,0 +1,41 @@ +//! Output formatting for calls-to command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::CalleeFunction; + +impl TableFormatter for ModuleGroupResult { + type Entry = CalleeFunction; + + fn format_header(&self) -> String { + if self.function_pattern.is_none() || self.function_pattern.as_ref().unwrap().is_empty() { + format!("Calls to: {}", self.module_pattern) + } else { + format!("Calls to: {}.{}", self.module_pattern, self.function_pattern.as_ref().unwrap()) + } + } + + fn format_empty_message(&self) -> String { + "No callers found.".to_string() + } + + fn format_summary(&self, total: usize, _module_count: usize) -> String { + format!("Found {} caller(s):", total) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + module_name.to_string() + } + + fn format_entry(&self, func: &CalleeFunction, _module: &str, _file: &str) -> String { + format!("{}/{}", func.name, func.arity) + } + + fn format_entry_details(&self, func: &CalleeFunction, module: &str, _file: &str) -> Vec { + // Use empty context file since callers come from different files + func.callers + .iter() + .map(|call| call.format_incoming(module, "")) + .collect() + } +} diff --git a/cli/src/commands/calls_to/output_tests.rs b/cli/src/commands/calls_to/output_tests.rs new file mode 100644 index 0000000..9e52915 --- /dev/null +++ b/cli/src/commands/calls_to/output_tests.rs @@ -0,0 +1,162 @@ +//! Output formatting tests for calls-to command. + +#[cfg(test)] +mod tests { + use super::super::execute::CalleeFunction; + use crate::types::{Call, FunctionRef, ModuleGroupResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Calls to: MyApp.Repo.get + +No callers found."; + + const SINGLE_TABLE: &str = "\ +Calls to: MyApp.Repo.get + +Found 1 caller(s): + +MyApp.Repo + get/2 + ← @ L12 MyApp.Accounts.get_user/1 (accounts.ex:L10:15)"; + + const MULTIPLE_TABLE: &str = "\ +Calls to: MyApp.Repo + +Found 2 caller(s): + +MyApp.Repo + get/2 + ← @ L12 MyApp.Accounts.get_user/1 (accounts.ex:L10:15) + ← @ L40 MyApp.Users.update_user/1 (users.ex:L35:45)"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Repo".to_string(), + "get".to_string(), + vec![], + ) + } + + #[fixture] + fn single_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Repo".to_string(), + "get".to_string(), + vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "get_user", + 1, + "", + "lib/my_app/accounts.ex", + 10, + 15, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 12, + call_type: Some("remote".to_string()), + depth: None, + }], + ) + } + + #[fixture] + fn multiple_result() -> ModuleGroupResult { + >::from_calls( + "MyApp.Repo".to_string(), + String::new(), + vec![ + Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "get_user", + 1, + "", + "lib/my_app/accounts.ex", + 10, + 15, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 12, + call_type: Some("remote".to_string()), + depth: None, + }, + Call { + caller: FunctionRef::with_definition( + "MyApp.Users", + "update_user", + 1, + "", + "lib/my_app/users.ex", + 35, + 45, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 40, + call_type: Some("remote".to_string()), + depth: None, + }, + ], + ) + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: ModuleGroupResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_to", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_to", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("calls_to", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/clusters/execute.rs b/cli/src/commands/clusters/execute.rs new file mode 100644 index 0000000..76ddd29 --- /dev/null +++ b/cli/src/commands/clusters/execute.rs @@ -0,0 +1,390 @@ +use std::collections::{HashMap, HashSet}; +use std::error::Error; + +use serde::Serialize; + +use super::ClustersCmd; +use crate::commands::Execute; +use crate::queries::clusters::get_module_calls; + +/// A single namespace cluster +#[derive(Debug, Clone, Serialize)] +pub struct ClusterInfo { + pub namespace: String, + pub module_count: usize, + pub internal_calls: i64, + pub outgoing_calls: i64, + pub incoming_calls: i64, + /// Cohesion: internal / (internal + outgoing + incoming) + /// Range 0-1, higher = more self-contained + pub cohesion: f64, + /// Instability: outgoing / (incoming + outgoing) + /// Range 0-1, 0 = stable (depended upon), 1 = unstable (depends on others) + pub instability: f64, +} + +/// A cross-namespace dependency edge +#[derive(Debug, Clone, Serialize)] +pub struct CrossDependency { + pub from_namespace: String, + pub to_namespace: String, + pub call_count: i64, +} + +/// Result of clusters analysis +#[derive(Debug, Serialize)] +pub struct ClustersResult { + pub depth: usize, + pub total_clusters: usize, + pub clusters: Vec, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub cross_dependencies: Vec, +} + +impl Execute for ClustersCmd { + type Output = ClustersResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + // Get all inter-module calls + let calls = get_module_calls(db, &self.common.project)?; + + // Extract namespace for each module and collect all unique modules + let mut all_modules = HashSet::new(); + for call in &calls { + all_modules.insert(call.caller_module.clone()); + all_modules.insert(call.callee_module.clone()); + } + + // Apply module filter if specified (simple substring matching for now) + // Complex regex filtering happens at query level in other commands + let filtered_modules: HashSet = if let Some(ref pattern) = self.module { + all_modules + .into_iter() + .filter(|m| m.contains(pattern)) + .collect() + } else { + all_modules + }; + + // Build namespace -> modules mapping + let mut namespace_modules: HashMap> = HashMap::new(); + for module in &filtered_modules { + let namespace = extract_namespace(module, self.depth); + namespace_modules + .entry(namespace) + .or_insert_with(HashSet::new) + .insert(module.clone()); + } + + // Count internal, outgoing, and incoming calls per namespace + let mut internal_calls: HashMap = HashMap::new(); + let mut outgoing_calls: HashMap = HashMap::new(); + let mut incoming_calls: HashMap = HashMap::new(); + let mut cross_deps: HashMap<(String, String), i64> = HashMap::new(); + + for call in calls { + let caller_ns = extract_namespace(&call.caller_module, self.depth); + let callee_ns = extract_namespace(&call.callee_module, self.depth); + + let caller_in_filter = filtered_modules.contains(&call.caller_module); + let callee_in_filter = filtered_modules.contains(&call.callee_module); + + // Skip calls where neither module is in our filtered set + if !caller_in_filter && !callee_in_filter { + continue; + } + + if caller_ns == callee_ns && caller_in_filter && callee_in_filter { + // Internal call (same namespace, both in filter) + *internal_calls.entry(caller_ns).or_insert(0) += 1; + } else if caller_ns != callee_ns { + // Cross-namespace call + // Count as outgoing for caller namespace (if in filter) + if caller_in_filter { + *outgoing_calls.entry(caller_ns.clone()).or_insert(0) += 1; + } + // Count as incoming for callee namespace (if in filter) + if callee_in_filter { + *incoming_calls.entry(callee_ns.clone()).or_insert(0) += 1; + } + + // Track cross-dependencies (from caller's perspective) + if caller_in_filter { + let key = (caller_ns, callee_ns); + *cross_deps.entry(key).or_insert(0) += 1; + } + } else if caller_in_filter && !callee_in_filter { + // Same namespace but callee outside filter - count as outgoing + *outgoing_calls.entry(caller_ns.clone()).or_insert(0) += 1; + } + } + + // Build cluster info + let mut clusters = Vec::new(); + for (namespace, modules) in namespace_modules { + let internal = internal_calls.get(&namespace).copied().unwrap_or(0); + let outgoing = outgoing_calls.get(&namespace).copied().unwrap_or(0); + let incoming = incoming_calls.get(&namespace).copied().unwrap_or(0); + + // Cohesion: internal / (internal + outgoing + incoming) + let total_interactions = internal + outgoing + incoming; + let cohesion = if total_interactions > 0 { + internal as f64 / total_interactions as f64 + } else { + 0.0 + }; + + // Instability: outgoing / (incoming + outgoing) + // 0 = stable (depended upon), 1 = unstable (depends on others) + let external_total = incoming + outgoing; + let instability = if external_total > 0 { + outgoing as f64 / external_total as f64 + } else { + 0.0 + }; + + clusters.push(ClusterInfo { + namespace, + module_count: modules.len(), + internal_calls: internal, + outgoing_calls: outgoing, + incoming_calls: incoming, + cohesion, + instability, + }); + } + + // Sort by cohesion descending, then by internal calls + clusters.sort_by(|a, b| { + b.cohesion + .partial_cmp(&a.cohesion) + .unwrap_or(std::cmp::Ordering::Equal) + .then_with(|| b.internal_calls.cmp(&a.internal_calls)) + }); + + // Build cross-dependencies if requested + let cross_dependencies = if self.show_dependencies { + let mut deps = Vec::new(); + for ((from_ns, to_ns), count) in cross_deps { + if from_ns != to_ns { + deps.push(CrossDependency { + from_namespace: from_ns, + to_namespace: to_ns, + call_count: count, + }); + } + } + // Sort by call_count descending + deps.sort_by(|a, b| b.call_count.cmp(&a.call_count)); + deps + } else { + Vec::new() + }; + + let total_clusters = clusters.len(); + + Ok(ClustersResult { + depth: self.depth, + total_clusters, + clusters, + cross_dependencies, + }) + } +} + +/// Extract namespace from a module name at the specified depth +/// +/// Example: "MyApp.Accounts.Users.Admin" at depth 2 becomes "MyApp.Accounts" +fn extract_namespace(module: &str, depth: usize) -> String { + module + .split('.') + .take(depth) + .collect::>() + .join(".") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_extract_namespace_depth_2() { + assert_eq!(extract_namespace("MyApp.Accounts.Users", 2), "MyApp.Accounts"); + } + + #[test] + fn test_extract_namespace_depth_1() { + assert_eq!(extract_namespace("MyApp.Accounts.Users", 1), "MyApp"); + } + + #[test] + fn test_extract_namespace_depth_3() { + assert_eq!(extract_namespace("MyApp.Accounts.Users", 3), "MyApp.Accounts.Users"); + } + + #[test] + fn test_extract_namespace_single_level() { + assert_eq!(extract_namespace("MyApp", 2), "MyApp"); + } + + #[test] + fn test_cohesion_calculation_all_internal() { + // If all calls are internal, cohesion should be 1.0 + let internal = 10; + let outgoing = 0; + let incoming = 0; + let total = internal + outgoing + incoming; + let cohesion = if total > 0 { + internal as f64 / total as f64 + } else { + 0.0 + }; + assert_eq!(cohesion, 1.0); + } + + #[test] + fn test_cohesion_calculation_all_external() { + // If all calls are external (outgoing + incoming), cohesion should be 0.0 + let internal = 0; + let outgoing = 5; + let incoming = 5; + let total = internal + outgoing + incoming; + let cohesion = if total > 0 { + internal as f64 / total as f64 + } else { + 0.0 + }; + assert_eq!(cohesion, 0.0); + } + + #[test] + fn test_cohesion_calculation_mixed() { + // Mixed: internal=45, outgoing=8, incoming=4 → 45/(45+8+4) = 45/57 ≈ 0.79 + let internal = 45; + let outgoing = 8; + let incoming = 4; + let total = internal + outgoing + incoming; + let cohesion = if total > 0 { + internal as f64 / total as f64 + } else { + 0.0 + }; + assert!((cohesion - 0.79).abs() < 0.01); + } + + #[test] + fn test_instability_calculation() { + // Instability = outgoing / (incoming + outgoing) + // outgoing=8, incoming=4 → 8/12 ≈ 0.67 (unstable, depends on others) + let outgoing = 8; + let incoming = 4; + let external_total = incoming + outgoing; + let instability = if external_total > 0 { + outgoing as f64 / external_total as f64 + } else { + 0.0 + }; + assert!((instability - 0.67).abs() < 0.01); + } + + #[test] + fn test_instability_stable_namespace() { + // A namespace with only incoming calls is stable (instability = 0) + let outgoing = 0; + let incoming = 10; + let external_total = incoming + outgoing; + let instability = if external_total > 0 { + outgoing as f64 / external_total as f64 + } else { + 0.0 + }; + assert_eq!(instability, 0.0); + } + + #[test] + fn test_instability_unstable_namespace() { + // A namespace with only outgoing calls is unstable (instability = 1) + let outgoing = 10; + let incoming = 0; + let external_total = incoming + outgoing; + let instability = if external_total > 0 { + outgoing as f64 / external_total as f64 + } else { + 0.0 + }; + assert_eq!(instability, 1.0); + } + + #[test] + fn test_clusters_cmd_structure() { + // Test that ClustersCmd is created correctly with defaults + let cmd = ClustersCmd { + depth: 2, + show_dependencies: false, + module: None, + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 100, + }, + }; + + assert_eq!(cmd.depth, 2); + assert!(!cmd.show_dependencies); + assert_eq!(cmd.module, None); + assert_eq!(cmd.common.project, "default"); + } + + #[test] + fn test_clusters_cmd_with_options() { + let cmd = ClustersCmd { + depth: 3, + show_dependencies: true, + module: Some("MyApp.Core".to_string()), + common: crate::commands::CommonArgs { + project: "custom".to_string(), + regex: false, + limit: 50, + }, + }; + + assert_eq!(cmd.depth, 3); + assert!(cmd.show_dependencies); + assert_eq!(cmd.module, Some("MyApp.Core".to_string())); + assert_eq!(cmd.common.project, "custom"); + } + + #[test] + fn test_cross_dependency_structure() { + let dep = CrossDependency { + from_namespace: "MyApp.Accounts".to_string(), + to_namespace: "MyApp.Repo".to_string(), + call_count: 23, + }; + + assert_eq!(dep.from_namespace, "MyApp.Accounts"); + assert_eq!(dep.to_namespace, "MyApp.Repo"); + assert_eq!(dep.call_count, 23); + } + + #[test] + fn test_cluster_info_structure() { + let cluster = ClusterInfo { + namespace: "MyApp.Accounts".to_string(), + module_count: 5, + internal_calls: 45, + outgoing_calls: 8, + incoming_calls: 4, + cohesion: 0.79, + instability: 0.67, + }; + + assert_eq!(cluster.namespace, "MyApp.Accounts"); + assert_eq!(cluster.module_count, 5); + assert_eq!(cluster.internal_calls, 45); + assert_eq!(cluster.outgoing_calls, 8); + assert_eq!(cluster.incoming_calls, 4); + assert!((cluster.cohesion - 0.79).abs() < 0.001); + assert!((cluster.instability - 0.67).abs() < 0.001); + } +} diff --git a/cli/src/commands/clusters/mod.rs b/cli/src/commands/clusters/mod.rs new file mode 100644 index 0000000..0c4e1e9 --- /dev/null +++ b/cli/src/commands/clusters/mod.rs @@ -0,0 +1,46 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Analyze module connectivity using namespace-based clustering +/// +/// Groups modules by namespace hierarchy and measures internal vs external connectivity. +/// Shows cohesion metrics (internal / (internal + external)) for each cluster. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search clusters # Show all namespace clusters + code_search clusters MyApp.Core # Filter to MyApp.Core namespace + code_search clusters --depth 2 # Cluster at depth 2 (e.g., MyApp.Accounts) + code_search clusters --depth 3 # Cluster at depth 3 (e.g., MyApp.Accounts.Auth) + code_search clusters --show-dependencies # Include cross-namespace call counts +")] +pub struct ClustersCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Namespace depth for clustering (default: 2) + #[arg(long, default_value = "2")] + pub depth: usize, + + /// Show cross-namespace dependencies + #[arg(long)] + pub show_dependencies: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for ClustersCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/clusters/output.rs b/cli/src/commands/clusters/output.rs new file mode 100644 index 0000000..e7e30f8 --- /dev/null +++ b/cli/src/commands/clusters/output.rs @@ -0,0 +1,81 @@ +//! Output formatting for clusters command results. + +use super::execute::ClustersResult; +use crate::output::Outputable; + +impl Outputable for ClustersResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + // Header with depth + lines.push(format!("Module Clusters (depth: {})", self.depth)); + lines.push(String::new()); + + if self.clusters.is_empty() { + lines.push("No clusters found.".to_string()); + return lines.join("\n"); + } + + // Summary + lines.push(format!("Found {} cluster(s):", self.total_clusters)); + lines.push(String::new()); + + // Calculate dynamic column width for namespace + let min_width = 7; // "Cluster".len() + let max_namespace_len = self + .clusters + .iter() + .map(|c| c.namespace.len()) + .max() + .unwrap_or(min_width); + let namespace_width = max_namespace_len.max(min_width); + + // Table header + // Columns: Cluster(dynamic) Modules(7) Internal(8) Out(5) In(5) Cohesion(8) Instab(6) + let header = format!( + "{:7} {:>8} {:>5} {:>5} {:>8} {:>6}", + "Cluster", + "Modules", + "Internal", + "Out", + "In", + "Cohesion", + "Instab", + width = namespace_width + ); + lines.push(header); + lines.push("-".repeat(namespace_width + 45)); + + // Table rows + for cluster in &self.clusters { + let row = format!( + "{:7} {:>8} {:>5} {:>5} {:>8.2} {:>6.2}", + cluster.namespace, + cluster.module_count, + cluster.internal_calls, + cluster.outgoing_calls, + cluster.incoming_calls, + cluster.cohesion, + cluster.instability, + width = namespace_width + ); + lines.push(row); + } + + // Cross-dependencies section + if !self.cross_dependencies.is_empty() { + lines.push(String::new()); + lines.push("Cross-Namespace Dependencies:".to_string()); + lines.push(String::new()); + + for dep in &self.cross_dependencies { + lines.push(format!( + " {} → {}: {} calls", + dep.from_namespace, dep.to_namespace, dep.call_count + )); + } + } + + lines.join("\n") + } +} diff --git a/cli/src/commands/complexity/cli_tests.rs b/cli/src/commands/complexity/cli_tests.rs new file mode 100644 index 0000000..30385a0 --- /dev/null +++ b/cli/src/commands/complexity/cli_tests.rs @@ -0,0 +1,119 @@ +//! CLI parsing tests for complexity command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_defaults_test! { + command: "complexity", + variant: Complexity, + required_args: [], + defaults: { + min: 1, + min_depth: 0, + exclude_generated: false, + module: None, + common.project: "default".to_string(), + common.regex: false, + common.limit: 100, + }, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_min, + args: ["--min", "10"], + field: min, + expected: 10, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_min_depth, + args: ["--min-depth", "3"], + field: min_depth, + expected: 3, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_exclude_generated, + args: ["--exclude-generated"], + field: exclude_generated, + expected: true, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_module, + args: ["MyApp.Accounts"], + field: module, + expected: Some("MyApp.Accounts".to_string()), + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_project, + args: ["--project", "my_project"], + field: common.project, + expected: "my_project".to_string(), + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_regex, + args: ["MyApp\\..*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_limit, + args: ["--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_with_limit_short, + args: ["-l", "20"], + field: common.limit, + expected: 20, + } + + crate::cli_limit_tests! { + command: "complexity", + variant: Complexity, + required_args: [], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + crate::cli_option_test! { + command: "complexity", + variant: Complexity, + test_name: test_combined_options, + args: ["MyApp", "--min", "15", "--min-depth", "2", "--exclude-generated", "-l", "30"], + field: min, + expected: 15, + } +} diff --git a/cli/src/commands/complexity/execute.rs b/cli/src/commands/complexity/execute.rs new file mode 100644 index 0000000..105742b --- /dev/null +++ b/cli/src/commands/complexity/execute.rs @@ -0,0 +1,85 @@ +use std::error::Error; + +use serde::Serialize; + +use super::ComplexityCmd; +use crate::commands::Execute; +use crate::queries::complexity::find_complexity_metrics; +use crate::types::ModuleCollectionResult; + +/// A single complexity metric entry +#[derive(Debug, Clone, Serialize)] +pub struct ComplexityEntry { + pub name: String, + pub arity: i64, + pub line: i64, + pub complexity: i64, + pub max_nesting_depth: i64, + pub lines: i64, +} + +impl Execute for ComplexityCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let metrics = find_complexity_metrics( + db, + self.min, + self.min_depth, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.exclude_generated, + self.common.limit, + )?; + + let total_items = metrics.len(); + + // Group by module + let items = crate::utils::group_by_module(metrics, |metric| { + let entry = ComplexityEntry { + name: metric.name, + arity: metric.arity, + line: metric.line, + complexity: metric.complexity, + max_nesting_depth: metric.max_nesting_depth, + lines: metric.lines, + }; + (metric.module, entry) + }); + + Ok(ModuleCollectionResult { + module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items, + items, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_complexity_cmd_structure() { + let cmd = ComplexityCmd { + min: 10, + min_depth: 3, + exclude_generated: false, + module: Some("MyApp".to_string()), + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 20, + }, + }; + + assert_eq!(cmd.min, 10); + assert_eq!(cmd.min_depth, 3); + assert!(!cmd.exclude_generated); + assert_eq!(cmd.module, Some("MyApp".to_string())); + } +} diff --git a/cli/src/commands/complexity/execute_tests.rs b/cli/src/commands/complexity/execute_tests.rs new file mode 100644 index 0000000..5f189fd --- /dev/null +++ b/cli/src/commands/complexity/execute_tests.rs @@ -0,0 +1,169 @@ +//! Execute tests for complexity command. + +#[cfg(test)] +mod tests { + use super::super::ComplexityCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // Test with default thresholds (min >= 1, depth >= 0) + crate::execute_test! { + test_name: test_complexity_default_thresholds, + fixture: populated_db, + cmd: ComplexityCmd { + min: 1, + min_depth: 0, + exclude_generated: false, + module: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // With default thresholds, all functions should be included (default complexity is 1) + assert_eq!(result.total_items, 15); + assert_eq!(result.items.len(), 5); // 5 modules + }, + } + + // Test with higher complexity threshold filters out lower complexity functions + crate::execute_test! { + test_name: test_complexity_high_threshold, + fixture: populated_db, + cmd: ComplexityCmd { + min: 10, + min_depth: 0, + exclude_generated: false, + module: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // No functions should exceed complexity 10 with default fixture + assert_eq!(result.total_items, 0); + assert!(result.items.is_empty()); + }, + } + + // Test with min depth filter + crate::execute_test! { + test_name: test_complexity_min_depth, + fixture: populated_db, + cmd: ComplexityCmd { + min: 1, + min_depth: 5, + exclude_generated: false, + module: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // No functions should have depth >= 5 with default fixture + assert_eq!(result.total_items, 0); + }, + } + + // Test with module filter + crate::execute_test! { + test_name: test_complexity_with_module_filter, + fixture: populated_db, + cmd: ComplexityCmd { + min: 1, + min_depth: 0, + exclude_generated: false, + module: Some("MyApp.Accounts".to_string()), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // Should only return MyApp.Accounts module (4 functions) + assert_eq!(result.total_items, 4); + assert_eq!(result.items.len(), 1); + assert_eq!(result.items[0].name, "MyApp.Accounts"); + assert_eq!(result.items[0].entries.len(), 4); + }, + } + + // Test with module regex filter + crate::execute_test! { + test_name: test_complexity_with_module_regex, + fixture: populated_db, + cmd: ComplexityCmd { + min: 1, + min_depth: 0, + exclude_generated: false, + module: Some("MyApp\\..*".to_string()), + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + // Should return all MyApp.* modules + assert_eq!(result.total_items, 15); + assert_eq!(result.items.len(), 5); + }, + } + + // Test limit parameter + crate::execute_test! { + test_name: test_complexity_with_limit, + fixture: populated_db, + cmd: ComplexityCmd { + min: 1, + min_depth: 0, + exclude_generated: false, + module: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 5, + }, + }, + assertions: |result| { + // With limit of 5, should get at most 5 functions + assert_eq!(result.total_items, 5); + }, + } + + // ========================================================================= + // Empty database tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: ComplexityCmd, + cmd: ComplexityCmd { + min: 1, + min_depth: 0, + exclude_generated: false, + module: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/complexity/mod.rs b/cli/src/commands/complexity/mod.rs new file mode 100644 index 0000000..d8e7d23 --- /dev/null +++ b/cli/src/commands/complexity/mod.rs @@ -0,0 +1,59 @@ +mod execute; +mod output; + +#[cfg(test)] +mod cli_tests; +#[cfg(test)] +mod execute_tests; +#[cfg(test)] +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Display complexity metrics for functions +/// +/// Shows functions with complexity scores and nesting depths. +/// Complexity is a measure of the cyclomatic complexity of a function, +/// and nesting depth is the maximum depth of nested control structures. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search complexity # Show all functions with complexity >= 1 + code_search complexity MyApp.Accounts # Filter to MyApp.Accounts module + code_search complexity --min 10 # Show functions with complexity >= 10 + code_search complexity --min-depth 3 # Show functions with nesting depth >= 3 + code_search complexity --exclude-generated # Exclude macro-generated functions + code_search complexity -l 20 # Show top 20 most complex functions +")] +pub struct ComplexityCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Minimum complexity threshold + #[arg(long, default_value = "1")] + pub min: i64, + + /// Minimum nesting depth threshold + #[arg(long, default_value = "0")] + pub min_depth: i64, + + /// Exclude macro-generated functions + #[arg(long)] + pub exclude_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for ComplexityCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/complexity/output.rs b/cli/src/commands/complexity/output.rs new file mode 100644 index 0000000..0acc4dc --- /dev/null +++ b/cli/src/commands/complexity/output.rs @@ -0,0 +1,40 @@ +//! Output formatting for complexity command results. + +use super::execute::ComplexityEntry; +use crate::output::TableFormatter; +use crate::types::ModuleCollectionResult; + +impl TableFormatter for ModuleCollectionResult { + type Entry = ComplexityEntry; + + fn format_header(&self) -> String { + "Complexity".to_string() + } + + fn format_empty_message(&self) -> String { + "No functions found with the specified complexity thresholds.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} function(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, entry: &ComplexityEntry, _module: &str, _file: &str) -> String { + format!( + "{}/{} complexity: {}, depth: {}, lines: {}", + entry.name, entry.arity, entry.complexity, entry.max_nesting_depth, entry.lines + ) + } + + fn blank_before_module(&self) -> bool { + true + } + + fn blank_after_summary(&self) -> bool { + false + } +} diff --git a/cli/src/commands/complexity/output_tests.rs b/cli/src/commands/complexity/output_tests.rs new file mode 100644 index 0000000..47b6d01 --- /dev/null +++ b/cli/src/commands/complexity/output_tests.rs @@ -0,0 +1,123 @@ +//! Output formatting tests for complexity command. + +#[cfg(test)] +mod tests { + use super::super::execute::ComplexityEntry; + use crate::output::Outputable; + use crate::types::{ModuleCollectionResult, ModuleGroup}; + + #[test] + fn test_format_table_single_function() { + let result = ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + entries: vec![ComplexityEntry { + name: "create_user".to_string(), + arity: 1, + line: 10, + complexity: 12, + max_nesting_depth: 4, + lines: 45, + }], + function_count: None, + }], + }; + + let output = result.format(crate::output::OutputFormat::Table); + assert!(output.contains("Complexity")); + assert!(output.contains("MyApp.Accounts")); + assert!(output.contains("create_user/1")); + assert!(output.contains("complexity: 12")); + assert!(output.contains("depth: 4")); + assert!(output.contains("lines: 45")); + } + + #[test] + fn test_format_table_empty() { + let result: ModuleCollectionResult = ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 0, + items: vec![], + }; + + let output = result.format(crate::output::OutputFormat::Table); + assert!(output.contains("Complexity")); + assert!(output.contains("No functions found")); + } + + #[test] + fn test_format_json() { + let result = ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + entries: vec![ComplexityEntry { + name: "create_user".to_string(), + arity: 1, + line: 10, + complexity: 12, + max_nesting_depth: 4, + lines: 45, + }], + function_count: None, + }], + }; + + let output = result.format(crate::output::OutputFormat::Json); + // Verify it's valid JSON + let parsed: serde_json::Value = + serde_json::from_str(&output).expect("Output should be valid JSON"); + assert_eq!( + parsed["total_items"], 1, + "total_items should be 1" + ); + assert_eq!( + parsed["items"][0]["entries"][0]["complexity"], 12, + "complexity should be 12" + ); + } + + #[test] + fn test_format_toon() { + let result = ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Service".to_string(), + file: "lib/my_app/service.ex".to_string(), + entries: vec![ComplexityEntry { + name: "process".to_string(), + arity: 1, + line: 5, + complexity: 8, + max_nesting_depth: 3, + lines: 25, + }], + function_count: None, + }], + }; + + let output = result.format(crate::output::OutputFormat::Toon); + // Verify it contains expected toon output elements + assert!(output.contains("MyApp.Service")); + assert!(output.contains("process")); + assert!(output.contains("8")); // complexity + } +} diff --git a/cli/src/commands/cycles/execute.rs b/cli/src/commands/cycles/execute.rs new file mode 100644 index 0000000..9eb497c --- /dev/null +++ b/cli/src/commands/cycles/execute.rs @@ -0,0 +1,274 @@ +//! Cycle detection execution and DFS-based cycle reconstruction. + +use std::collections::{HashMap, HashSet}; +use std::error::Error; + +use serde::Serialize; + +use super::CyclesCmd; +use crate::commands::Execute; +use crate::queries::cycles::find_cycle_edges; + +/// A single cycle found in the module dependency graph +#[derive(Debug, Clone, Serialize)] +pub struct Cycle { + /// Length of the cycle (number of modules) + pub length: usize, + /// Ordered path of modules: A → B → C → A + pub modules: Vec, +} + +/// Result of cycle detection +#[derive(Debug, Serialize)] +pub struct CyclesResult { + /// Total number of distinct cycles found + pub total_cycles: usize, + /// Total number of unique modules involved in cycles + pub modules_in_cycles: usize, + /// The detected cycles + pub cycles: Vec, +} + +impl Execute for CyclesCmd { + type Output = CyclesResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + // Get cycle edges from the database + let edges = find_cycle_edges( + db, + &self.common.project, + self.module.as_deref(), + )?; + + if edges.is_empty() { + return Ok(CyclesResult { + total_cycles: 0, + modules_in_cycles: 0, + cycles: vec![], + }); + } + + // Build adjacency list from edges + let mut graph: HashMap> = HashMap::new(); + let mut all_modules = HashSet::new(); + + for edge in &edges { + graph + .entry(edge.from.clone()) + .or_insert_with(Vec::new) + .push(edge.to.clone()); + all_modules.insert(edge.from.clone()); + all_modules.insert(edge.to.clone()); + } + + // Find cycles using DFS from each node + let mut cycles = find_all_cycles(&graph, &all_modules); + + // Filter by max_length if provided + if let Some(max_len) = self.max_length { + cycles.retain(|c| c.length <= max_len); + } + + // Filter by involving module if provided + if let Some(involving) = &self.involving { + cycles.retain(|c| c.modules.iter().any(|m| m.contains(involving))); + } + + // Deduplicate cycles (same modules in different starting positions are the same cycle) + cycles = deduplicate_cycles(cycles); + + // Count unique modules in cycles + let modules_in_cycles: HashSet<_> = cycles + .iter() + .flat_map(|c| c.modules.iter().cloned()) + .collect(); + + Ok(CyclesResult { + total_cycles: cycles.len(), + modules_in_cycles: modules_in_cycles.len(), + cycles, + }) + } +} + +/// Find all cycles starting from each node in the graph using DFS +fn find_all_cycles(graph: &HashMap>, all_modules: &HashSet) -> Vec { + let mut cycles = Vec::new(); + + for start_node in all_modules { + let found = dfs_find_cycles(graph, start_node, start_node, vec![], &mut HashSet::new()); + cycles.extend(found); + } + + cycles +} + +/// DFS to find cycles starting from a given node +fn dfs_find_cycles( + graph: &HashMap>, + current: &str, + start: &str, + path: Vec, + visited: &mut HashSet, +) -> Vec { + let mut cycles = Vec::new(); + let mut new_path = path.clone(); + new_path.push(current.to_string()); + + // If we've revisited the start node and have more than one edge in the path, + // we've found a cycle + if current == start && !path.is_empty() { + // Only report if we haven't already found this cycle + // (cycles of length > 1 where start != first path node) + if path.len() > 0 { + cycles.push(Cycle { + length: new_path.len() - 1, // Don't count the repeated start node + modules: path.clone(), + }); + } + return cycles; + } + + // Prevent infinite recursion on the same node in the current path + if new_path.len() > 1 && path.contains(¤t.to_string()) { + return cycles; + } + + // Explore neighbors + if let Some(neighbors) = graph.get(current) { + for neighbor in neighbors { + let found = dfs_find_cycles(graph, neighbor, start, new_path.clone(), visited); + cycles.extend(found); + } + } + + cycles +} + +/// Remove duplicate cycles (same modules in different orders/rotations) +fn deduplicate_cycles(cycles: Vec) -> Vec { + let mut unique = Vec::new(); + let mut seen = HashSet::new(); + + for cycle in cycles { + // Normalize the cycle representation: sort to get canonical form + let mut sorted = cycle.modules.clone(); + sorted.sort(); + let canonical = format!("{:?}", sorted); + + if !seen.contains(&canonical) { + seen.insert(canonical); + unique.push(cycle); + } + } + + // Sort cycles by length and first module for consistent output + unique.sort_by(|a, b| { + a.length.cmp(&b.length).then_with(|| { + a.modules + .first() + .cmp(&b.modules.first()) + }) + }); + + unique +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_find_cycles_simple_two_module_cycle() { + let mut graph = HashMap::new(); + graph.insert("A".to_string(), vec!["B".to_string()]); + graph.insert("B".to_string(), vec!["A".to_string()]); + + let mut modules = HashSet::new(); + modules.insert("A".to_string()); + modules.insert("B".to_string()); + + let cycles = find_all_cycles(&graph, &modules); + let unique = deduplicate_cycles(cycles); + + // A-B-A should be detected as one cycle + assert_eq!(unique.len(), 1); + assert_eq!(unique[0].length, 2); + assert!(unique[0].modules.contains(&"A".to_string())); + assert!(unique[0].modules.contains(&"B".to_string())); + } + + #[test] + fn test_find_cycles_three_module_cycle() { + let mut graph = HashMap::new(); + graph.insert("A".to_string(), vec!["B".to_string()]); + graph.insert("B".to_string(), vec!["C".to_string()]); + graph.insert("C".to_string(), vec!["A".to_string()]); + + let mut modules = HashSet::new(); + modules.insert("A".to_string()); + modules.insert("B".to_string()); + modules.insert("C".to_string()); + + let cycles = find_all_cycles(&graph, &modules); + let unique = deduplicate_cycles(cycles); + + assert_eq!(unique.len(), 1); + assert_eq!(unique[0].length, 3); + } + + #[test] + fn test_find_cycles_no_cycles() { + let mut graph = HashMap::new(); + graph.insert("A".to_string(), vec!["B".to_string()]); + graph.insert("B".to_string(), vec!["C".to_string()]); + + let mut modules = HashSet::new(); + modules.insert("A".to_string()); + modules.insert("B".to_string()); + modules.insert("C".to_string()); + + let cycles = find_all_cycles(&graph, &modules); + assert_eq!(cycles.len(), 0); + } + + #[test] + fn test_deduplicate_cycles() { + let cycles = vec![ + Cycle { + length: 2, + modules: vec!["A".to_string(), "B".to_string()], + }, + Cycle { + length: 2, + modules: vec!["B".to_string(), "A".to_string()], + }, + ]; + + let unique = deduplicate_cycles(cycles); + assert_eq!(unique.len(), 1); + } + + #[test] + fn test_max_length_filter() { + let mut graph = HashMap::new(); + graph.insert("A".to_string(), vec!["B".to_string()]); + graph.insert("B".to_string(), vec!["C".to_string()]); + graph.insert("C".to_string(), vec!["A".to_string()]); + + let mut modules = HashSet::new(); + modules.insert("A".to_string()); + modules.insert("B".to_string()); + modules.insert("C".to_string()); + + let cycles = find_all_cycles(&graph, &modules); + let unique = deduplicate_cycles(cycles); + + assert_eq!(unique.len(), 1); + assert_eq!(unique[0].length, 3); + + // Filter to max_length 2 + let filtered: Vec<_> = unique.iter().filter(|c| c.length <= 2).cloned().collect(); + assert_eq!(filtered.len(), 0); + } +} diff --git a/cli/src/commands/cycles/mod.rs b/cli/src/commands/cycles/mod.rs new file mode 100644 index 0000000..c1b96c7 --- /dev/null +++ b/cli/src/commands/cycles/mod.rs @@ -0,0 +1,45 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Detect circular dependencies between modules +/// +/// Analyzes the call graph to find cycles where modules directly or indirectly +/// depend on each other, creating circular imports or call loops. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search cycles # Find all cycles + code_search cycles MyApp.Core # Filter to MyApp.Core namespace + code_search cycles --max-length 3 # Only show cycles of length <= 3 + code_search cycles --involving MyApp.Accounts # Only cycles involving Accounts +")] +pub struct CyclesCmd { + /// Module filter pattern (substring or regex with -r) + pub module: Option, + + /// Maximum cycle length to find + #[arg(long)] + pub max_length: Option, + + /// Only show cycles involving this module (substring match) + #[arg(long)] + pub involving: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for CyclesCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/cycles/output.rs b/cli/src/commands/cycles/output.rs new file mode 100644 index 0000000..0393853 --- /dev/null +++ b/cli/src/commands/cycles/output.rs @@ -0,0 +1,125 @@ +//! Output formatting for cycles command results. + +use super::execute::CyclesResult; +use crate::output::Outputable; + +impl Outputable for CyclesResult { + fn to_table(&self) -> String { + if self.cycles.is_empty() { + return "No circular dependencies found.\n".to_string(); + } + + let mut output = String::new(); + output.push_str("Circular Dependencies\n\n"); + output.push_str(&format!("Found {} cycle(s):\n\n", self.total_cycles)); + + for (idx, cycle) in self.cycles.iter().enumerate() { + output.push_str(&format!("Cycle {} (length {}):\n", idx + 1, cycle.length)); + + // Format the cycle path with arrows + for (i, module) in cycle.modules.iter().enumerate() { + if i == 0 { + output.push_str(" "); + } else { + output.push_str("\n → "); + } + output.push_str(module); + } + + // Show closing arrow back to first module + if !cycle.modules.is_empty() { + output.push_str("\n → "); + output.push_str(&cycle.modules[0]); + } + + output.push_str("\n\n"); + } + + output.push_str(&format!( + "Total: {} module(s) involved in cycles\n", + self.modules_in_cycles + )); + + output + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::commands::cycles::execute::Cycle; + + #[test] + fn test_cycles_output_format_empty() { + let result = CyclesResult { + total_cycles: 0, + modules_in_cycles: 0, + cycles: vec![], + }; + + let output = result.to_table(); + assert!(output.contains("No circular dependencies found")); + } + + #[test] + fn test_cycles_output_format_single_cycle() { + let result = CyclesResult { + total_cycles: 1, + modules_in_cycles: 2, + cycles: vec![Cycle { + length: 2, + modules: vec!["MyApp.Accounts".to_string(), "MyApp.Auth".to_string()], + }], + }; + + let output = result.to_table(); + assert!(output.contains("Cycle 1 (length 2)")); + assert!(output.contains("MyApp.Accounts")); + assert!(output.contains("MyApp.Auth")); + assert!(output.contains("Total: 2 module(s) involved in cycles")); + } + + #[test] + fn test_cycles_output_format_multiple_cycles() { + let result = CyclesResult { + total_cycles: 2, + modules_in_cycles: 5, + cycles: vec![ + Cycle { + length: 2, + modules: vec!["A".to_string(), "B".to_string()], + }, + Cycle { + length: 3, + modules: vec![ + "C".to_string(), + "D".to_string(), + "E".to_string(), + ], + }, + ], + }; + + let output = result.to_table(); + assert!(output.contains("Cycle 1 (length 2)")); + assert!(output.contains("Cycle 2 (length 3)")); + assert!(output.contains("Total: 5 module(s) involved in cycles")); + } + + #[test] + fn test_cycles_output_json() { + let result = CyclesResult { + total_cycles: 1, + modules_in_cycles: 2, + cycles: vec![Cycle { + length: 2, + modules: vec!["A".to_string(), "B".to_string()], + }], + }; + + let json = serde_json::to_string(&result).unwrap(); + assert!(json.contains("total_cycles")); + assert!(json.contains("modules_in_cycles")); + assert!(json.contains("cycles")); + } +} diff --git a/cli/src/commands/depended_by/cli_tests.rs b/cli/src/commands/depended_by/cli_tests.rs new file mode 100644 index 0000000..40fab0f --- /dev/null +++ b/cli/src/commands/depended_by/cli_tests.rs @@ -0,0 +1,56 @@ +//! CLI parsing tests for depended-by command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_required_arg_test! { + command: "depended-by", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_option_test! { + command: "depended-by", + variant: DependedBy, + test_name: test_with_module, + args: ["MyApp.Repo"], + field: module, + expected: "MyApp.Repo", + } + + crate::cli_option_test! { + command: "depended-by", + variant: DependedBy, + test_name: test_with_regex, + args: ["MyApp\\..*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "depended-by", + variant: DependedBy, + test_name: test_with_limit, + args: ["MyApp.Repo", "--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_limit_tests! { + command: "depended-by", + variant: DependedBy, + required_args: ["MyApp.Repo"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/depended_by/execute.rs b/cli/src/commands/depended_by/execute.rs new file mode 100644 index 0000000..ccb45ab --- /dev/null +++ b/cli/src/commands/depended_by/execute.rs @@ -0,0 +1,127 @@ +use std::collections::BTreeMap; +use std::error::Error; + +use serde::Serialize; + +use super::DependedByCmd; +use crate::commands::Execute; +use crate::queries::depended_by::find_dependents; +use crate::types::{Call, ModuleGroupResult, ModuleGroup}; + +/// A target function being called in the dependency module +#[derive(Debug, Clone, Serialize)] +pub struct DependentTarget { + pub function: String, + pub arity: i64, + pub line: i64, +} + +/// A caller function in a dependent module +#[derive(Debug, Clone, Serialize)] +pub struct DependentCaller { + pub function: String, + pub arity: i64, + pub kind: String, + pub start_line: i64, + pub end_line: i64, + pub file: String, + pub targets: Vec, +} + +impl ModuleGroupResult { + /// Build a grouped structure from flat calls + pub fn from_calls(target_module: String, calls: Vec) -> Self { + let total_items = calls.len(); + + if calls.is_empty() { + return ModuleGroupResult { + module_pattern: target_module, + function_pattern: None, + total_items: 0, + items: vec![], + }; + } + + // Group by caller_module -> caller_function -> targets + // Using BTreeMap for automatic sorting by module and function key + let mut by_module: BTreeMap>> = BTreeMap::new(); + for call in &calls { + by_module + .entry(call.caller.module.to_string()) + .or_default() + .entry((call.caller.name.to_string(), call.caller.arity)) + .or_default() + .push(call); + } + + let items: Vec> = by_module + .into_iter() + .map(|(module_name, callers_map)| { + // Determine module file from first caller in first function + let module_file = callers_map + .values() + .next() + .and_then(|calls| calls.first()) + .and_then(|call| call.caller.file.as_deref()) + .unwrap_or("") + .to_string(); + + let entries: Vec = callers_map + .into_iter() + .map(|((func_name, arity), func_calls)| { + let first = func_calls[0]; + + let targets: Vec = func_calls + .iter() + .map(|c| DependentTarget { + function: c.callee.name.to_string(), + arity: c.callee.arity, + line: c.line, + }) + .collect(); + + DependentCaller { + function: func_name, + arity, + kind: first.caller.kind.as_deref().unwrap_or("").to_string(), + start_line: first.caller.start_line.unwrap_or(0), + end_line: first.caller.end_line.unwrap_or(0), + file: first.caller.file.as_deref().unwrap_or("").to_string(), + targets, + } + }) + .collect(); + + ModuleGroup { + name: module_name, + file: module_file, + entries, + function_count: None, + } + }) + .collect(); + + ModuleGroupResult { + module_pattern: target_module, + function_pattern: None, + total_items, + items, + } + } +} + +impl Execute for DependedByCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let calls = find_dependents( + db, + &self.module, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(>::from_calls(self.module, calls)) + } +} diff --git a/cli/src/commands/depended_by/execute_tests.rs b/cli/src/commands/depended_by/execute_tests.rs new file mode 100644 index 0000000..6f6a0ee --- /dev/null +++ b/cli/src/commands/depended_by/execute_tests.rs @@ -0,0 +1,112 @@ +//! Execute tests for depended-by command. + +#[cfg(test)] +mod tests { + use super::super::DependedByCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // MyApp.Repo is depended on by: Accounts (3 calls), Service (1 call via do_fetch) + crate::execute_test! { + test_name: test_depended_by_single_module, + fixture: populated_db, + cmd: DependedByCmd { + module: "MyApp.Repo".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.items.len(), 2); + assert!(result.items.iter().any(|m| m.name == "MyApp.Accounts")); + assert!(result.items.iter().any(|m| m.name == "MyApp.Service")); + }, + } + + crate::execute_test! { + test_name: test_depended_by_counts_calls, + fixture: populated_db, + cmd: DependedByCmd { + module: "MyApp.Repo".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // Accounts has 3 callers, Service has 1 + let accounts = result.items.iter().find(|m| m.name == "MyApp.Accounts").unwrap(); + let service = result.items.iter().find(|m| m.name == "MyApp.Service").unwrap(); + let accounts_calls: usize = accounts.entries.iter().map(|c| c.targets.len()).sum(); + let service_calls: usize = service.entries.iter().map(|c| c.targets.len()).sum(); + assert_eq!(accounts_calls, 3); + assert_eq!(service_calls, 1); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_depended_by_no_match, + fixture: populated_db, + cmd: DependedByCmd { + module: "NonExistent".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: items, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_all_match_test! { + test_name: test_depended_by_excludes_self, + fixture: populated_db, + cmd: DependedByCmd { + module: "MyApp.Repo".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + collection: items, + condition: |m| m.name != "MyApp.Repo", + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: DependedByCmd, + cmd: DependedByCmd { + module: "MyApp".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/depended_by/mod.rs b/cli/src/commands/depended_by/mod.rs new file mode 100644 index 0000000..d52f684 --- /dev/null +++ b/cli/src/commands/depended_by/mod.rs @@ -0,0 +1,34 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Show what modules depend on a given module (incoming module dependencies) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search depended-by MyApp.Repo # Who depends on Repo? + code_search depended-by 'Ecto\\..*' -r # Who depends on Ecto modules?")] +pub struct DependedByCmd { + /// Module name (exact match or pattern with --regex) + pub module: String, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for DependedByCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/depended_by/output.rs b/cli/src/commands/depended_by/output.rs new file mode 100644 index 0000000..abb7081 --- /dev/null +++ b/cli/src/commands/depended_by/output.rs @@ -0,0 +1,48 @@ +//! Output formatting for depended-by command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::DependentCaller; + +impl TableFormatter for ModuleGroupResult { + type Entry = DependentCaller; + + fn format_header(&self) -> String { + format!("Modules that depend on: {}", self.module_pattern) + } + + fn format_empty_message(&self) -> String { + "No dependents found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} call(s) from {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, caller: &DependentCaller, _module: &str, _file: &str) -> String { + let kind_str = if caller.kind.is_empty() { + String::new() + } else { + format!(" [{}]", caller.kind) + }; + // Extract just the filename from path + let filename = caller.file.rsplit('/').next().unwrap_or(&caller.file); + format!( + "{}/{}{} ({}:L{}:{}):", + caller.function, caller.arity, kind_str, + filename, caller.start_line, caller.end_line + ) + } + + fn format_entry_details(&self, caller: &DependentCaller, _module: &str, _file: &str) -> Vec { + caller + .targets + .iter() + .map(|target| format!("→ @ L{} {}/{}", target.line, target.function, target.arity)) + .collect() + } +} diff --git a/cli/src/commands/depended_by/output_tests.rs b/cli/src/commands/depended_by/output_tests.rs new file mode 100644 index 0000000..d1a27d7 --- /dev/null +++ b/cli/src/commands/depended_by/output_tests.rs @@ -0,0 +1,176 @@ +//! Output formatting tests for depended-by command. + +#[cfg(test)] +mod tests { + use super::super::execute::{DependentCaller, DependentTarget}; + use crate::types::{ModuleGroupResult, ModuleGroup}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Modules that depend on: MyApp.Repo + +No dependents found."; + + const SINGLE_TABLE: &str = "\ +Modules that depend on: MyApp.Repo + +Found 1 call(s) from 1 module(s): + +MyApp.Service: + fetch/1 [def] (service.ex:L10:20): + → @ L15 get/2"; + + const MULTIPLE_TABLE: &str = "\ +Modules that depend on: MyApp.Repo + +Found 2 call(s) from 2 module(s): + +MyApp.Controller: + show/1 [def] (controller.ex:L15:25): + → @ L20 get/2 +MyApp.Service: + fetch/1 [def] (service.ex:L10:20): + → @ L15 get/2"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: None, + total_items: 0, + items: vec![], + } + } + + #[fixture] + fn single_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Service".to_string(), + file: String::new(), + entries: vec![DependentCaller { + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "lib/service.ex".to_string(), + targets: vec![DependentTarget { + function: "get".to_string(), + arity: 2, + line: 15, + }], + }], + function_count: None, + }], + } + } + + #[fixture] + fn multiple_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: None, + total_items: 2, + items: vec![ + ModuleGroup { + name: "MyApp.Controller".to_string(), + file: String::new(), + entries: vec![DependentCaller { + function: "show".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 15, + end_line: 25, + file: "lib/controller.ex".to_string(), + targets: vec![DependentTarget { + function: "get".to_string(), + arity: 2, + line: 20, + }], + }], + function_count: None, + }, + ModuleGroup { + name: "MyApp.Service".to_string(), + file: String::new(), + entries: vec![DependentCaller { + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "lib/service.ex".to_string(), + targets: vec![DependentTarget { + function: "get".to_string(), + arity: 2, + line: 15, + }], + }], + function_count: None, + }, + ], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: ModuleGroupResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depended_by", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depended_by", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depended_by", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/depends_on/cli_tests.rs b/cli/src/commands/depends_on/cli_tests.rs new file mode 100644 index 0000000..18a8d2b --- /dev/null +++ b/cli/src/commands/depends_on/cli_tests.rs @@ -0,0 +1,56 @@ +//! CLI parsing tests for depends-on command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_required_arg_test! { + command: "depends-on", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_option_test! { + command: "depends-on", + variant: DependsOn, + test_name: test_with_module, + args: ["MyApp.Accounts"], + field: module, + expected: "MyApp.Accounts", + } + + crate::cli_option_test! { + command: "depends-on", + variant: DependsOn, + test_name: test_with_regex, + args: ["MyApp\\..*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "depends-on", + variant: DependsOn, + test_name: test_with_limit, + args: ["MyApp.Accounts", "--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_limit_tests! { + command: "depends-on", + variant: DependsOn, + required_args: ["MyApp.Accounts"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/depends_on/execute.rs b/cli/src/commands/depends_on/execute.rs new file mode 100644 index 0000000..a645581 --- /dev/null +++ b/cli/src/commands/depends_on/execute.rs @@ -0,0 +1,83 @@ +use std::collections::BTreeMap; +use std::error::Error; + +use serde::Serialize; + +use super::DependsOnCmd; +use crate::commands::Execute; +use crate::queries::depends_on::find_dependencies; +use crate::types::{Call, ModuleGroupResult}; +use crate::utils::convert_to_module_groups; + +/// A function in a dependency module being called +#[derive(Debug, Clone, Serialize)] +pub struct DependencyFunction { + pub name: String, + pub arity: i64, + pub callers: Vec, +} + +impl ModuleGroupResult { + /// Build a grouped structure from flat calls + pub fn from_calls(source_module: String, calls: Vec) -> Self { + let total_items = calls.len(); + + if calls.is_empty() { + return ModuleGroupResult { + module_pattern: source_module, + function_pattern: None, + total_items: 0, + items: vec![], + }; + } + + // Group by callee_module -> callee_function -> callers + // Using BTreeMap for automatic sorting + let mut by_module: BTreeMap>> = BTreeMap::new(); + for call in calls { + by_module + .entry(call.callee.module.to_string()) + .or_default() + .entry((call.callee.name.to_string(), call.callee.arity)) + .or_default() + .push(call); + } + + // Convert to ModuleGroup structure + let items = convert_to_module_groups( + by_module, + |(func_name, arity), callers| DependencyFunction { + name: func_name, + arity, + callers, + }, + // File is intentionally empty because dependencies are the grouping key, + // and a module can depend on functions defined across multiple files. + // The dependency targets themselves carry file information where needed. + |_module, _map| String::new(), + ); + + ModuleGroupResult { + module_pattern: source_module, + function_pattern: None, + total_items, + items, + } + } +} + +impl Execute for DependsOnCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let calls = find_dependencies( + db, + &self.module, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(>::from_calls(self.module, calls)) + } +} diff --git a/cli/src/commands/depends_on/execute_tests.rs b/cli/src/commands/depends_on/execute_tests.rs new file mode 100644 index 0000000..dc23276 --- /dev/null +++ b/cli/src/commands/depends_on/execute_tests.rs @@ -0,0 +1,110 @@ +//! Execute tests for depends-on command. + +#[cfg(test)] +mod tests { + use super::super::DependsOnCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // Controller depends on: Accounts (2 calls: list_users, get_user) and Service (1 call: process) + crate::execute_test! { + test_name: test_depends_on_single_module, + fixture: populated_db, + cmd: DependsOnCmd { + module: "MyApp.Controller".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.items.len(), 2); + assert!(result.items.iter().any(|m| m.name == "MyApp.Accounts")); + assert!(result.items.iter().any(|m| m.name == "MyApp.Service")); + }, + } + + // Service depends on: Repo (1 call via do_fetch) and Notifier (1 call via process) + // Self-calls (process→fetch, fetch→do_fetch) are excluded + crate::execute_test! { + test_name: test_depends_on_counts_calls, + fixture: populated_db, + cmd: DependsOnCmd { + module: "MyApp.Service".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.items.len(), 2); + assert!(result.items.iter().any(|m| m.name == "MyApp.Repo")); + assert!(result.items.iter().any(|m| m.name == "MyApp.Notifier")); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_depends_on_no_match, + fixture: populated_db, + cmd: DependsOnCmd { + module: "NonExistent".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: items, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_all_match_test! { + test_name: test_depends_on_excludes_self, + fixture: populated_db, + cmd: DependsOnCmd { + module: "MyApp.Repo".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + collection: items, + condition: |m| m.name != "MyApp.Repo", + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: DependsOnCmd, + cmd: DependsOnCmd { + module: "MyApp".to_string(), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/depends_on/mod.rs b/cli/src/commands/depends_on/mod.rs new file mode 100644 index 0000000..ea72d6b --- /dev/null +++ b/cli/src/commands/depends_on/mod.rs @@ -0,0 +1,34 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Show what modules a given module depends on (outgoing module dependencies) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search depends-on MyApp.Accounts # What does Accounts depend on? + code_search depends-on 'MyApp\\.Web.*' -r # Dependencies of Web modules")] +pub struct DependsOnCmd { + /// Module name (exact match or pattern with --regex) + pub module: String, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for DependsOnCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/depends_on/output.rs b/cli/src/commands/depends_on/output.rs new file mode 100644 index 0000000..784e713 --- /dev/null +++ b/cli/src/commands/depends_on/output.rs @@ -0,0 +1,37 @@ +//! Output formatting for depends-on command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::DependencyFunction; + +impl TableFormatter for ModuleGroupResult { + type Entry = DependencyFunction; + + fn format_header(&self) -> String { + format!("Dependencies of: {}", self.module_pattern) + } + + fn format_empty_message(&self) -> String { + "No dependencies found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} call(s) to {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, func: &DependencyFunction, _module: &str, _file: &str) -> String { + format!("{}/{}:", func.name, func.arity) + } + + fn format_entry_details(&self, func: &DependencyFunction, module: &str, _file: &str) -> Vec { + // Use empty context since callers come from different files + func.callers + .iter() + .map(|call| call.format_incoming(module, "")) + .collect() + } +} diff --git a/cli/src/commands/depends_on/output_tests.rs b/cli/src/commands/depends_on/output_tests.rs new file mode 100644 index 0000000..7c74549 --- /dev/null +++ b/cli/src/commands/depends_on/output_tests.rs @@ -0,0 +1,194 @@ +//! Output formatting tests for depends-on command. + +#[cfg(test)] +mod tests { + use super::super::execute::DependencyFunction; + use crate::types::{Call, FunctionRef, ModuleGroupResult, ModuleGroup}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Dependencies of: MyApp.Controller + +No dependencies found."; + + const SINGLE_TABLE: &str = "\ +Dependencies of: MyApp.Controller + +Found 1 call(s) to 1 module(s): + +MyApp.Service: + process/1: + ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12)"; + + const MULTIPLE_TABLE: &str = "\ +Dependencies of: MyApp.Controller + +Found 2 call(s) to 2 module(s): + +MyApp.Service: + process/1: + ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12) +Phoenix.View: + render/2: + ← @ L20 MyApp.Controller.show/1 [def] (controller.ex:L15:25)"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Controller".to_string(), + function_pattern: None, + total_items: 0, + items: vec![], + } + } + + #[fixture] + fn single_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Controller".to_string(), + function_pattern: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Service".to_string(), + file: String::new(), + entries: vec![DependencyFunction { + name: "process".to_string(), + arity: 1, + callers: vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Controller", + "index", + 1, + "def", + "lib/controller.ex", + 5, + 12, + ), + callee: FunctionRef::new("MyApp.Service", "process", 1), + line: 7, + call_type: None, + depth: None, + }], + }], + function_count: None, + }], + } + } + + #[fixture] + fn multiple_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Controller".to_string(), + function_pattern: None, + total_items: 2, + items: vec![ + ModuleGroup { + name: "MyApp.Service".to_string(), + file: String::new(), + entries: vec![DependencyFunction { + name: "process".to_string(), + arity: 1, + callers: vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Controller", + "index", + 1, + "def", + "lib/controller.ex", + 5, + 12, + ), + callee: FunctionRef::new("MyApp.Service", "process", 1), + line: 7, + call_type: None, + depth: None, + }], + }], + function_count: None, + }, + ModuleGroup { + name: "Phoenix.View".to_string(), + file: String::new(), + entries: vec![DependencyFunction { + name: "render".to_string(), + arity: 2, + callers: vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Controller", + "show", + 1, + "def", + "lib/controller.ex", + 15, + 25, + ), + callee: FunctionRef::new("Phoenix.View", "render", 2), + line: 20, + call_type: None, + depth: None, + }], + }], + function_count: None, + }, + ], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: ModuleGroupResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depends_on", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depends_on", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("depends_on", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/describe/descriptions.rs b/cli/src/commands/describe/descriptions.rs new file mode 100644 index 0000000..e90f5cf --- /dev/null +++ b/cli/src/commands/describe/descriptions.rs @@ -0,0 +1,488 @@ +//! Centralized descriptions for all available commands. + +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum CommandCategory { + Query, + Analysis, + Search, + Type, + Module, + Other, +} + +impl std::fmt::Display for CommandCategory { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Query => write!(f, "Query Commands"), + Self::Analysis => write!(f, "Analysis Commands"), + Self::Search => write!(f, "Search Commands"), + Self::Type => write!(f, "Type Search Commands"), + Self::Module => write!(f, "Module Commands"), + Self::Other => write!(f, "Other Commands"), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Example { + pub description: String, + pub command: String, +} + +impl Example { + pub fn new(description: &str, command: &str) -> Self { + Self { + description: description.to_string(), + command: command.to_string(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommandDescription { + pub name: String, + pub brief: String, + pub category: CommandCategory, + pub description: String, + pub usage: String, + pub examples: Vec, + pub related: Vec, +} + +impl CommandDescription { + pub fn new( + name: &str, + brief: &str, + category: CommandCategory, + description: &str, + usage: &str, + ) -> Self { + Self { + name: name.to_string(), + brief: brief.to_string(), + category, + description: description.to_string(), + usage: usage.to_string(), + examples: Vec::new(), + related: Vec::new(), + } + } + + pub fn with_examples(mut self, examples: Vec) -> Self { + self.examples = examples; + self + } + + pub fn with_related(mut self, related: Vec<&str>) -> Self { + self.related = related.iter().map(|s| s.to_string()).collect(); + self + } +} + +/// Get all available command descriptions +pub fn all_descriptions() -> Vec { + vec![ + // Query Commands + CommandDescription::new( + "calls-to", + "Find callers of a given function", + CommandCategory::Query, + "Finds all functions that call a specific function. Use this to answer: 'Who calls this function?'", + "code_search calls-to [FUNCTION] [ARITY] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all callers of MyApp.Repo.get/2", "code_search calls-to MyApp.Repo get 2"), + Example::new("Find callers of any function in a module", "code_search calls-to MyApp.Repo"), + ]) + .with_related(vec!["calls-from", "trace", "path"]), + + CommandDescription::new( + "calls-from", + "Find what a function calls", + CommandCategory::Query, + "Finds all functions that are called by a specific function. Use this to answer: 'What does this function call?'", + "code_search calls-from [FUNCTION] [ARITY] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all functions called by MyApp.Repo.get/2", "code_search calls-from MyApp.Repo get 2"), + Example::new("Find what a module calls", "code_search calls-from MyApp.Accounts"), + ]) + .with_related(vec!["calls-to", "trace", "path"]), + + CommandDescription::new( + "trace", + "Forward call trace from a function", + CommandCategory::Query, + "Traces call chains forward from a starting function. Shows the full path of calls that can be reached from a given function.", + "code_search trace [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Trace all calls from a function", "code_search trace MyApp.API create_user"), + Example::new("Limit trace depth to 3 levels", "code_search trace MyApp.API create_user --depth 3"), + ]) + .with_related(vec!["calls-from", "reverse-trace", "path"]), + + CommandDescription::new( + "reverse-trace", + "Backward call trace to a function", + CommandCategory::Query, + "Traces call chains backward to a target function. Shows all code paths that can lead to a given function.", + "code_search reverse-trace [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all paths leading to a function", "code_search reverse-trace MyApp.API validate_token"), + Example::new("Limit trace depth to 2 levels", "code_search reverse-trace MyApp.API validate_token --depth 2"), + ]) + .with_related(vec!["calls-to", "trace", "path"]), + + CommandDescription::new( + "path", + "Find a call path between two functions", + CommandCategory::Query, + "Finds one or more call paths connecting two functions. Useful for understanding how code flows from a source to a target.", + "code_search path --from-module --from-function --to-module --to-function ", + ) + .with_examples(vec![ + Example::new("Find call path between two functions", "code_search path --from-module MyApp.API --from-function create_user --to-module MyApp.DB --to-function insert"), + ]) + .with_related(vec!["trace", "reverse-trace", "calls-from"]), + + // Analysis Commands + CommandDescription::new( + "hotspots", + "Find high-connectivity functions", + CommandCategory::Analysis, + "Identifies functions with the most incoming or outgoing calls. \ + Use -k incoming (default) for most-called functions, -k outgoing for functions that call many others, \ + -k total for highest combined connectivity, or -k ratio for boundary functions.", + "code_search hotspots [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Most called functions", "code_search hotspots"), + Example::new("Functions calling many others", "code_search hotspots -k outgoing"), + Example::new("Highest total connections", "code_search hotspots -k total"), + Example::new("Boundary functions (high ratio)", "code_search hotspots -k ratio"), + Example::new("Filter to namespace", "code_search hotspots MyApp -l 20"), + ]) + .with_related(vec!["god-modules", "boundaries", "complexity"]), + + CommandDescription::new( + "unused", + "Find functions that are never called", + CommandCategory::Analysis, + "Identifies functions with no incoming calls. Use -p to find dead code (unused private functions) \ + or -P to find entry points (public functions not called internally). Use -x to exclude \ + compiler-generated functions like __struct__, __info__, etc.", + "code_search unused [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all unused functions", "code_search unused"), + Example::new("Filter to a specific module", "code_search unused MyApp.Utils"), + Example::new("Find dead code (unused private)", "code_search unused -p"), + Example::new("Find entry points (unused public)", "code_search unused -Px"), + ]) + .with_related(vec!["hotspots", "duplicates", "large-functions"]), + + CommandDescription::new( + "god-modules", + "Find god modules - modules with high function count, LoC, and connectivity", + CommandCategory::Analysis, + "Identifies modules that are overly large or have too much responsibility. \ + Use --min-functions, --min-loc, and --min-total to set thresholds for function count, \ + lines of code, and connectivity respectively.", + "code_search god-modules [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all god modules", "code_search god-modules"), + Example::new("Filter to a namespace", "code_search god-modules MyApp.Core"), + Example::new("With minimum 500 LoC", "code_search god-modules --min-loc 500"), + Example::new("With minimum 30 functions", "code_search god-modules --min-functions 30"), + ]) + .with_related(vec!["hotspots", "boundaries", "complexity"]), + + CommandDescription::new( + "boundaries", + "Find boundary modules with high fan-in but low fan-out", + CommandCategory::Analysis, + "Identifies modules that many others depend on but have few dependencies. These are key integration points. \ + Use --min-incoming to set a threshold for incoming calls and --min-ratio for the fan-in/fan-out ratio.", + "code_search boundaries [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all boundary modules", "code_search boundaries"), + Example::new("Filter to a namespace", "code_search boundaries MyApp.Web"), + Example::new("Set minimum incoming calls", "code_search boundaries --min-incoming 5"), + Example::new("Set minimum ratio threshold", "code_search boundaries --min-ratio 3.0"), + ]) + .with_related(vec!["god-modules", "hotspots", "depends-on"]), + + CommandDescription::new( + "duplicates", + "Find functions with identical or near-identical implementations", + CommandCategory::Analysis, + "Identifies duplicate code that could be consolidated into reusable functions. \ + Uses AST matching by default; use --exact for source-level matching. \ + Use --by-module to rank modules by duplication count. \ + Use --exclude-generated to filter out macro-generated functions.", + "code_search duplicates [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all duplicate functions", "code_search duplicates"), + Example::new("Find duplicates in a module", "code_search duplicates MyApp.Utils"), + Example::new("Use exact source matching", "code_search duplicates --exact"), + Example::new("Rank modules by duplication", "code_search duplicates --by-module"), + Example::new("Exclude generated functions", "code_search duplicates --exclude-generated"), + ]) + .with_related(vec!["unused", "large-functions", "hotspots"]), + + CommandDescription::new( + "complexity", + "Display complexity metrics for functions", + CommandCategory::Analysis, + "Shows cyclomatic complexity and nesting depth for functions. \ + Use --min and --min-depth to filter by thresholds. Generated functions are excluded by default.", + "code_search complexity [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Show all functions with complexity >= 1", "code_search complexity"), + Example::new("Filter to a namespace", "code_search complexity MyApp.Accounts"), + Example::new("Find highly complex functions", "code_search complexity --min 10"), + Example::new("Find deeply nested functions", "code_search complexity --min-depth 3"), + ]) + .with_related(vec!["large-functions", "many-clauses", "hotspots"]), + + CommandDescription::new( + "large-functions", + "Find large functions that may need refactoring", + CommandCategory::Analysis, + "Identifies functions that are large by line count (50+ lines by default), sorted by size descending. \ + Use --min-lines to adjust the threshold. Generated functions are excluded by default.", + "code_search large-functions [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all large functions", "code_search large-functions"), + Example::new("Filter to a namespace", "code_search large-functions MyApp.Web"), + Example::new("Find functions with 100+ lines", "code_search large-functions --min-lines 100"), + Example::new("Include generated functions", "code_search large-functions --include-generated"), + ]) + .with_related(vec!["complexity", "many-clauses", "hotspots"]), + + CommandDescription::new( + "many-clauses", + "Find functions with many pattern-matched heads", + CommandCategory::Analysis, + "Identifies functions with many clauses/definitions (5+ by default), sorted by clause count descending. \ + Use --min-clauses to adjust the threshold. Generated functions are excluded by default.", + "code_search many-clauses [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find functions with many clauses", "code_search many-clauses"), + Example::new("Filter to a namespace", "code_search many-clauses MyApp.Web"), + Example::new("Find functions with 10+ clauses", "code_search many-clauses --min-clauses 10"), + Example::new("Include generated functions", "code_search many-clauses --include-generated"), + ]) + .with_related(vec!["complexity", "large-functions", "hotspots"]), + + CommandDescription::new( + "cycles", + "Detect circular dependencies between modules", + CommandCategory::Analysis, + "Finds circular dependencies in the module dependency graph, which indicate architectural issues. \ + Use --max-length to limit cycle size and --involving to find cycles containing a specific module.", + "code_search cycles [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all circular dependencies", "code_search cycles"), + Example::new("Filter to a namespace", "code_search cycles MyApp.Core"), + Example::new("Find short cycles only", "code_search cycles --max-length 3"), + Example::new("Find cycles involving a module", "code_search cycles --involving MyApp.Accounts"), + ]) + .with_related(vec!["depends-on", "depended-by", "boundaries"]), + + // Search Commands + CommandDescription::new( + "search", + "Search for modules or functions by name pattern", + CommandCategory::Search, + "Finds modules or functions matching a given pattern. Use this as a starting point for other analyses.", + "code_search search [-k modules|functions] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find modules containing 'User'", "code_search search User"), + Example::new("Find functions starting with 'get_'", "code_search search get_ -k functions"), + Example::new("Use regex pattern", "code_search search -r '^MyApp\\.API'"), + ]) + .with_related(vec!["location", "function", "browse-module"]), + + CommandDescription::new( + "location", + "Find where a function is defined", + CommandCategory::Search, + "Shows the file path and line numbers where a function is defined. Useful for quickly navigating to code.", + "code_search location [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find any function named 'validate'", "code_search location validate"), + Example::new("Find location of a function in a module", "code_search location get MyApp.Repo"), + ]) + .with_related(vec!["search", "function", "browse-module"]), + + CommandDescription::new( + "function", + "Show function signature", + CommandCategory::Search, + "Displays the full signature of a function including arguments, return type, and metadata.", + "code_search function [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Show function signature", "code_search function MyApp.Repo get -a 2"), + ]) + .with_related(vec!["search", "location", "accepts"]), + + CommandDescription::new( + "browse-module", + "Browse all definitions in a module or file", + CommandCategory::Module, + "Lists all functions, structs, and other definitions in a module. Great for exploring unfamiliar code.", + "code_search browse-module -m [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Browse a module", "code_search browse-module -m MyApp.Accounts"), + Example::new("Browse with limit", "code_search browse-module -m MyApp.Accounts --limit 50"), + ]) + .with_related(vec!["search", "location", "struct-usage"]), + + // Type Search Commands + CommandDescription::new( + "accepts", + "Find functions accepting a specific type pattern", + CommandCategory::Type, + "Finds all functions that have a parameter matching a type pattern. Useful for finding consumers of a type.", + "code_search accepts [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find functions accepting a type", "code_search accepts User.t"), + Example::new("Use regex for type pattern", "code_search accepts 'list\\(.*\\)' -r"), + ]) + .with_related(vec!["returns", "struct-usage", "function"]), + + CommandDescription::new( + "returns", + "Find functions returning a specific type pattern", + CommandCategory::Type, + "Finds all functions that return a type matching a pattern. Useful for finding providers of a type.", + "code_search returns [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find functions returning a type", "code_search returns ':ok'"), + Example::new("Use regex for type pattern", "code_search returns 'tuple\\(.*\\)' -r"), + ]) + .with_related(vec!["accepts", "struct-usage", "function"]), + + CommandDescription::new( + "struct-usage", + "Find functions that work with a given struct type", + CommandCategory::Type, + "Lists functions that accept or return a specific type pattern. Use --by-module to aggregate counts per module.", + "code_search struct-usage [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find all functions using a struct", "code_search struct-usage User.t"), + Example::new("Summarize by module", "code_search struct-usage User.t --by-module"), + ]) + .with_related(vec!["accepts", "returns", "browse-module"]), + + // Module Commands + CommandDescription::new( + "depends-on", + "Show what modules a given module depends on", + CommandCategory::Module, + "Lists all modules that a given module calls or depends on. Shows outgoing module dependencies.", + "code_search depends-on [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find module dependencies", "code_search depends-on MyApp.API"), + ]) + .with_related(vec!["depended-by", "cycles", "boundaries"]), + + CommandDescription::new( + "depended-by", + "Show what modules depend on a given module", + CommandCategory::Module, + "Lists all modules that call or depend on a given module. Shows incoming module dependencies.", + "code_search depended-by [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Find modules that depend on this one", "code_search depended-by MyApp.Repo"), + ]) + .with_related(vec!["depends-on", "cycles", "boundaries"]), + + CommandDescription::new( + "clusters", + "Analyze module connectivity using namespace-based clustering", + CommandCategory::Module, + "Groups modules into clusters based on their namespace structure and interdependencies.\n\n\ + Output columns:\n\ + - Internal: calls between modules within the same namespace\n\ + - Out: calls from this namespace to other namespaces\n\ + - In: calls from other namespaces into this one\n\ + - Cohesion: internal / (internal + out + in) — higher = more self-contained\n\ + - Instab: out / (in + out) — 0 = stable (depended upon), 1 = unstable (depends on others)", + "code_search clusters [MODULE] [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Show all namespace clusters", "code_search clusters"), + Example::new("Filter to a namespace", "code_search clusters MyApp.Core"), + Example::new("Cluster at depth 3", "code_search clusters --depth 3"), + Example::new("Show cross-namespace dependencies", "code_search clusters --show-dependencies"), + ]) + .with_related(vec!["god-modules", "boundaries", "depends-on"]), + + // Other Commands + CommandDescription::new( + "setup", + "Create database schema without importing data", + CommandCategory::Other, + "Initializes a new database with the required schema for storing call graph data.", + "code_search setup [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Create database schema", "code_search setup --db ./my_project.db"), + Example::new("Force recreate", "code_search setup --db ./my_project.db --force"), + ]) + .with_related(vec!["import"]), + + CommandDescription::new( + "import", + "Import a call graph JSON file into the database", + CommandCategory::Other, + "Loads call graph data from a JSON file into the database. Must run setup first.", + "code_search import --file [OPTIONS]", + ) + .with_examples(vec![ + Example::new("Import call graph data", "code_search import --file call_graph.json"), + ]) + .with_related(vec!["setup"]), + ] +} + +/// Get a single command description by name +pub fn get_description(name: &str) -> Option { + all_descriptions().into_iter().find(|d| d.name == name) +} + +/// Get all descriptions grouped by category +pub fn descriptions_by_category() -> std::collections::BTreeMap> { + let mut map = std::collections::BTreeMap::new(); + + for desc in all_descriptions() { + map.entry(desc.category) + .or_insert_with(Vec::new) + .push((desc.name.clone(), desc.brief.clone())); + } + + map +} diff --git a/cli/src/commands/describe/execute.rs b/cli/src/commands/describe/execute.rs new file mode 100644 index 0000000..2e2db5a --- /dev/null +++ b/cli/src/commands/describe/execute.rs @@ -0,0 +1,146 @@ +use std::error::Error; +use serde::Serialize; + +use super::DescribeCmd; +use super::descriptions::{CommandDescription, get_description, descriptions_by_category}; +use crate::commands::Execute; + +/// Output for listing all commands by category +#[derive(Debug, Clone, Serialize)] +pub struct CategoryListing { + pub category: String, + pub commands: Vec<(String, String)>, // (name, brief) +} + +/// Output for describe mode +#[derive(Debug, Serialize)] +#[serde(untagged)] +pub enum DescribeMode { + ListAll { + categories: Vec, + }, + Specific { + descriptions: Vec, + }, +} + +/// Result of the describe command +#[derive(Debug, Serialize)] +pub struct DescribeResult { + #[serde(flatten)] + pub mode: DescribeMode, +} + +impl Execute for DescribeCmd { + type Output = DescribeResult; + + fn execute(self, _db: &cozo::DbInstance) -> Result> { + if self.commands.is_empty() { + // List all commands grouped by category + let categories_map = descriptions_by_category(); + let mut categories = Vec::new(); + + for (category, commands) in categories_map { + categories.push(CategoryListing { + category: category.to_string(), + commands, + }); + } + + Ok(DescribeResult { + mode: DescribeMode::ListAll { categories }, + }) + } else { + // Get descriptions for specified commands + let mut descriptions = Vec::new(); + + for cmd_name in self.commands { + match get_description(&cmd_name) { + Some(desc) => descriptions.push(desc), + None => { + return Err(format!("Unknown command: '{}'", cmd_name).into()); + } + } + } + + Ok(DescribeResult { + mode: DescribeMode::Specific { descriptions }, + }) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_describe_all_lists_categories() { + let cmd = DescribeCmd { + commands: vec![], + }; + + let result = cmd.execute(&Default::default()).expect("Should succeed"); + + match result.mode { + DescribeMode::ListAll { ref categories } => { + assert!(!categories.is_empty()); + // Check we have commands in categories + let total_commands: usize = categories.iter().map(|c| c.commands.len()).sum(); + assert!(total_commands > 0); + } + _ => panic!("Expected ListAll mode"), + } + } + + #[test] + fn test_describe_specific_command() { + let cmd = DescribeCmd { + commands: vec!["calls-to".to_string()], + }; + + let result = cmd.execute(&Default::default()).expect("Should succeed"); + + match result.mode { + DescribeMode::Specific { ref descriptions } => { + assert_eq!(descriptions.len(), 1); + assert_eq!(descriptions[0].name, "calls-to"); + } + _ => panic!("Expected Specific mode"), + } + } + + #[test] + fn test_describe_multiple_commands() { + let cmd = DescribeCmd { + commands: vec![ + "calls-to".to_string(), + "calls-from".to_string(), + "trace".to_string(), + ], + }; + + let result = cmd.execute(&Default::default()).expect("Should succeed"); + + match result.mode { + DescribeMode::Specific { ref descriptions } => { + assert_eq!(descriptions.len(), 3); + let names: Vec<_> = descriptions.iter().map(|d| d.name.as_str()).collect(); + assert!(names.contains(&"calls-to")); + assert!(names.contains(&"calls-from")); + assert!(names.contains(&"trace")); + } + _ => panic!("Expected Specific mode"), + } + } + + #[test] + fn test_describe_unknown_command() { + let cmd = DescribeCmd { + commands: vec!["nonexistent".to_string()], + }; + + let result = cmd.execute(&Default::default()); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/describe/mod.rs b/cli/src/commands/describe/mod.rs new file mode 100644 index 0000000..f80a258 --- /dev/null +++ b/cli/src/commands/describe/mod.rs @@ -0,0 +1,30 @@ +mod descriptions; +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Display detailed documentation about available commands +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search describe # List all available commands + code_search describe calls-to # Detailed info about calls-to command + code_search describe calls-to calls-from trace # Describe multiple commands")] +pub struct DescribeCmd { + /// Command(s) to describe (if empty, lists all) + pub commands: Vec, +} + +impl CommandRunner for DescribeCmd { + fn run(self, _db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(_db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/describe/output.rs b/cli/src/commands/describe/output.rs new file mode 100644 index 0000000..7353376 --- /dev/null +++ b/cli/src/commands/describe/output.rs @@ -0,0 +1,162 @@ +//! Output formatting for describe command results. + +use crate::output::Outputable; +use super::execute::{DescribeResult, DescribeMode, CategoryListing}; +use super::descriptions::CommandDescription; + +impl Outputable for DescribeResult { + fn to_table(&self) -> String { + match &self.mode { + DescribeMode::ListAll { categories } => format_list_all(categories), + DescribeMode::Specific { descriptions } => format_specific(descriptions), + } + } +} + +fn format_list_all(categories: &[CategoryListing]) -> String { + let mut output = String::new(); + output.push_str("Available Commands\n"); + output.push_str("\n"); + + for category in categories { + output.push_str(&format!("{}:\n", category.category)); + for (name, brief) in &category.commands { + output.push_str(&format!(" {:<20} {}\n", name, brief)); + } + output.push_str("\n"); + } + + output.push_str("Use 'code_search describe ' for detailed information.\n"); + output +} + +fn format_specific(descriptions: &[CommandDescription]) -> String { + let mut output = String::new(); + + for (i, desc) in descriptions.iter().enumerate() { + if i > 0 { + output.push_str("\n"); + output.push_str("================================================================================\n"); + output.push_str("\n"); + } + + // Title + output.push_str(&format!("{} - {}\n", desc.name, desc.brief)); + output.push_str("\n"); + + // Description + output.push_str("DESCRIPTION\n"); + output.push_str(&format!(" {}\n", desc.description)); + output.push_str("\n"); + + // Usage + output.push_str("USAGE\n"); + output.push_str(&format!(" {}\n", desc.usage)); + output.push_str("\n"); + + // Examples + if !desc.examples.is_empty() { + output.push_str("EXAMPLES\n"); + for example in &desc.examples { + output.push_str(&format!(" # {}\n", example.description)); + output.push_str(&format!(" {}\n", example.command)); + output.push_str("\n"); + } + } + + // Related commands + if !desc.related.is_empty() { + output.push_str("RELATED COMMANDS\n"); + for related in &desc.related { + output.push_str(&format!(" {}\n", related)); + } + output.push_str("\n"); + } + } + + output +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::commands::describe::descriptions::Example; + + #[test] + fn test_format_list_all() { + let categories = vec![ + CategoryListing { + category: "Query Commands".to_string(), + commands: vec![ + ("calls-to".to_string(), "Find callers of a given function".to_string()), + ("calls-from".to_string(), "Find what a function calls".to_string()), + ], + }, + CategoryListing { + category: "Analysis Commands".to_string(), + commands: vec![ + ("hotspots".to_string(), "Find high-connectivity functions".to_string()), + ], + }, + ]; + + let output = format_list_all(&categories); + assert!(output.contains("Available Commands")); + assert!(output.contains("Query Commands")); + assert!(output.contains("Analysis Commands")); + assert!(output.contains("calls-to")); + assert!(output.contains("hotspots")); + assert!(output.contains("Use 'code_search describe ' for detailed information.")); + } + + #[test] + fn test_format_specific_single() { + let descriptions = vec![ + CommandDescription::new( + "calls-to", + "Find callers of a given function", + crate::commands::describe::descriptions::CommandCategory::Query, + "Finds all functions that call a specific function.", + "code_search calls-to -m -f ", + ) + .with_examples(vec![ + Example::new("Find all callers", "code_search calls-to -m MyApp.Repo -f get"), + ]) + .with_related(vec!["calls-from", "trace"]), + ]; + + let output = format_specific(&descriptions); + assert!(output.contains("calls-to - Find callers of a given function")); + assert!(output.contains("DESCRIPTION")); + assert!(output.contains("USAGE")); + assert!(output.contains("EXAMPLES")); + assert!(output.contains("Find all callers")); + assert!(output.contains("RELATED COMMANDS")); + assert!(output.contains("calls-from")); + } + + #[test] + fn test_format_specific_multiple() { + let descriptions = vec![ + CommandDescription::new( + "calls-to", + "Find callers", + crate::commands::describe::descriptions::CommandCategory::Query, + "Finds all callers.", + "code_search calls-to", + ), + CommandDescription::new( + "calls-from", + "Find callees", + crate::commands::describe::descriptions::CommandCategory::Query, + "Finds what is called.", + "code_search calls-from", + ), + ]; + + let output = format_specific(&descriptions); + assert!(output.contains("calls-to")); + assert!(output.contains("calls-from")); + assert!(output.contains("================================================================================")); + } +} diff --git a/cli/src/commands/duplicates/cli_tests.rs b/cli/src/commands/duplicates/cli_tests.rs new file mode 100644 index 0000000..1feeea5 --- /dev/null +++ b/cli/src/commands/duplicates/cli_tests.rs @@ -0,0 +1,107 @@ +//! CLI parsing tests for duplicates command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // Duplicates has no required args + crate::cli_defaults_test! { + command: "duplicates", + variant: Duplicates, + required_args: [], + defaults: { + common.project: "default", + common.regex: false, + exact: false, + by_module: false, + exclude_generated: false, + common.limit: 100, + }, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_module, + args: ["MyApp"], + field: module, + expected: Some("MyApp".to_string()), + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_exact, + args: ["--exact"], + field: exact, + expected: true, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_by_module, + args: ["--by-module"], + field: by_module, + expected: true, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_exclude_generated, + args: ["--exclude-generated"], + field: exclude_generated, + expected: true, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_regex, + args: ["MyApp.*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_limit, + args: ["--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_limit_short, + args: ["-l", "75"], + field: common.limit, + expected: 75, + } + + crate::cli_option_test! { + command: "duplicates", + variant: Duplicates, + test_name: test_with_project, + args: ["--project", "my_project"], + field: common.project, + expected: "my_project", + } + + crate::cli_error_test! { + command: "duplicates", + test_name: test_limit_zero_rejected, + args: ["--limit", "0"], + } + + crate::cli_error_test! { + command: "duplicates", + test_name: test_limit_exceeds_max_rejected, + args: ["--limit", "1001"], + } +} diff --git a/cli/src/commands/duplicates/execute.rs b/cli/src/commands/duplicates/execute.rs new file mode 100644 index 0000000..8428e2a --- /dev/null +++ b/cli/src/commands/duplicates/execute.rs @@ -0,0 +1,191 @@ +use std::collections::BTreeMap; +use std::error::Error; + +use serde::Serialize; + +use super::DuplicatesCmd; +use crate::commands::Execute; +use crate::queries::duplicates::find_duplicates; + +// ============================================================================= +// Detailed mode types (default) +// ============================================================================= + +/// Result structure for duplicates command - grouped by hash +#[derive(Debug, Clone, Serialize)] +pub struct DuplicatesResult { + pub total_groups: usize, + pub total_duplicates: usize, + pub groups: Vec, +} + +/// A group of functions with the same hash +#[derive(Debug, Clone, Serialize)] +pub struct DuplicateGroup { + pub hash: String, + pub functions: Vec, +} + +/// A function within a duplicate group +#[derive(Debug, Clone, Serialize)] +pub struct DuplicateFunctionEntry { + pub module: String, + pub name: String, + pub arity: i64, + pub line: i64, + pub file: String, +} + +// ============================================================================= +// ByModule mode types +// ============================================================================= + +/// Result structure for --by-module mode - ranked by module +#[derive(Debug, Clone, Serialize)] +pub struct DuplicatesByModuleResult { + pub total_modules: usize, + pub total_duplicates: i64, + pub modules: Vec, +} + +/// A module with its duplicate functions +#[derive(Debug, Clone, Serialize)] +pub struct ModuleDuplicates { + pub name: String, + pub duplicate_count: i64, + pub top_duplicates: Vec, +} + +/// Summary of a duplicated function +#[derive(Debug, Clone, Serialize)] +pub struct DuplicateSummary { + pub name: String, + pub arity: i64, + pub copy_count: i64, +} + +// ============================================================================= +// Output enum +// ============================================================================= + +/// Output type that can be either detailed or aggregated by module +#[derive(Debug, Serialize)] +#[serde(untagged)] +pub enum DuplicatesOutput { + Detailed(DuplicatesResult), + ByModule(DuplicatesByModuleResult), +} + +// ============================================================================= +// Execute implementation +// ============================================================================= + +impl Execute for DuplicatesCmd { + type Output = DuplicatesOutput; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let functions = find_duplicates( + db, + &self.common.project, + self.module.as_deref(), + self.common.regex, + self.exact, + self.exclude_generated, + )?; + + if self.by_module { + Ok(DuplicatesOutput::ByModule(build_by_module_result(functions))) + } else { + Ok(DuplicatesOutput::Detailed(build_detailed_result(functions))) + } + } +} + +fn build_detailed_result( + functions: Vec, +) -> DuplicatesResult { + // Group by hash + let mut groups_map: BTreeMap> = BTreeMap::new(); + + for func in functions { + let entry = DuplicateFunctionEntry { + module: func.module, + name: func.name, + arity: func.arity, + line: func.line, + file: func.file, + }; + groups_map.entry(func.hash).or_default().push(entry); + } + + // Convert to result format + let total_duplicates = groups_map.values().map(|v| v.len()).sum(); + let groups = groups_map + .into_iter() + .map(|(hash, functions)| DuplicateGroup { hash, functions }) + .collect::>(); + let total_groups = groups.len(); + + DuplicatesResult { + total_groups, + total_duplicates, + groups, + } +} + +fn build_by_module_result( + functions: Vec, +) -> DuplicatesByModuleResult { + // Group by module first + let mut module_map: BTreeMap> = BTreeMap::new(); + + for func in functions { + module_map + .entry(func.module) + .or_default() + .push((func.hash, func.name, func.arity)); + } + + // Aggregate by module and find top duplicates per module + let mut modules = Vec::new(); + for (module_name, funcs) in module_map { + // Group by function name/arity to count copies + let mut func_map: BTreeMap<(String, i64), i64> = BTreeMap::new(); + + for (_hash, name, arity) in &funcs { + let key = (name.clone(), *arity); + *func_map.entry(key).or_insert(0) += 1; + } + + // Convert to DuplicateSummary and sort by copy count (descending) + let mut summaries: Vec = func_map + .into_iter() + .map(|((name, arity), count)| DuplicateSummary { + name, + arity, + copy_count: count, + }) + .collect(); + + summaries.sort_by(|a, b| b.copy_count.cmp(&a.copy_count)); + + let duplicate_count = summaries.len() as i64; + modules.push(ModuleDuplicates { + name: module_name, + duplicate_count, + top_duplicates: summaries, + }); + } + + // Sort modules by duplicate count (descending) + modules.sort_by(|a, b| b.duplicate_count.cmp(&a.duplicate_count)); + + let total_duplicates: i64 = modules.iter().map(|m| m.duplicate_count).sum(); + let total_modules = modules.len(); + + DuplicatesByModuleResult { + total_modules, + total_duplicates, + modules, + } +} diff --git a/cli/src/commands/duplicates/execute_tests.rs b/cli/src/commands/duplicates/execute_tests.rs new file mode 100644 index 0000000..0cf47db --- /dev/null +++ b/cli/src/commands/duplicates/execute_tests.rs @@ -0,0 +1,230 @@ +//! Execute tests for duplicates command. + +#[cfg(test)] +mod tests { + use super::super::DuplicatesCmd; + use crate::commands::duplicates::execute::DuplicatesOutput; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests (detailed mode - default) + // ========================================================================= + + crate::execute_test! { + test_name: test_duplicates_empty_db, + fixture: populated_db, + cmd: DuplicatesCmd { + module: None, + by_module: false, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // Result should be Detailed variant + match result { + DuplicatesOutput::Detailed(res) => { + // If there are no duplicates, we should have 0 groups + assert!(res.groups.is_empty() || !res.groups.is_empty()); + } + _ => panic!("Expected Detailed variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_with_module_filter, + fixture: populated_db, + cmd: DuplicatesCmd { + module: Some("MyApp".to_string()), + by_module: false, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::Detailed(res) => { + assert!(res.groups.is_empty() || !res.groups.is_empty()); + } + _ => panic!("Expected Detailed variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_with_exact_flag, + fixture: populated_db, + cmd: DuplicatesCmd { + module: None, + by_module: false, + exact: true, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::Detailed(res) => { + assert!(res.groups.is_empty() || !res.groups.is_empty()); + } + _ => panic!("Expected Detailed variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_with_regex_filter, + fixture: populated_db, + cmd: DuplicatesCmd { + module: Some("^MyApp\\.Controller$".to_string()), + by_module: false, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::Detailed(res) => { + assert!(res.groups.is_empty() || !res.groups.is_empty()); + } + _ => panic!("Expected Detailed variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_structure, + fixture: populated_db, + cmd: DuplicatesCmd { + module: None, + by_module: false, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::Detailed(res) => { + let _ = res.total_groups; + let _ = res.total_duplicates; + for group in &res.groups { + assert!(!group.hash.is_empty()); + assert!(group.functions.len() >= 2); + } + } + _ => panic!("Expected Detailed variant"), + } + }, + } + + // ========================================================================= + // By-module mode tests + // ========================================================================= + + crate::execute_test! { + test_name: test_duplicates_by_module, + fixture: populated_db, + cmd: DuplicatesCmd { + module: None, + by_module: true, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::ByModule(res) => { + let _ = res.total_modules; + let _ = res.total_duplicates; + for module in &res.modules { + assert!(!module.name.is_empty()); + assert!(module.duplicate_count > 0); + } + } + _ => panic!("Expected ByModule variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_by_module_with_filter, + fixture: populated_db, + cmd: DuplicatesCmd { + module: Some("MyApp".to_string()), + by_module: true, + exact: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::ByModule(res) => { + for module in &res.modules { + assert!(module.name.contains("MyApp")); + } + } + _ => panic!("Expected ByModule variant"), + } + }, + } + + crate::execute_test! { + test_name: test_duplicates_exclude_generated, + fixture: populated_db, + cmd: DuplicatesCmd { + module: None, + by_module: false, + exact: false, + exclude_generated: true, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + DuplicatesOutput::Detailed(res) => { + // With exclude_generated, generated functions should be filtered out + assert!(res.groups.is_empty() || !res.groups.is_empty()); + } + _ => panic!("Expected Detailed variant"), + } + }, + } +} diff --git a/cli/src/commands/duplicates/mod.rs b/cli/src/commands/duplicates/mod.rs new file mode 100644 index 0000000..08940b7 --- /dev/null +++ b/cli/src/commands/duplicates/mod.rs @@ -0,0 +1,49 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions with identical or near-identical implementations +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search duplicates # Find all duplicate functions + code_search duplicates MyApp # Filter to specific module + code_search duplicates --by-module # Rank modules by duplication + code_search duplicates --exact # Use exact source matching + code_search duplicates --exclude-generated # Exclude macro-generated functions")] +pub struct DuplicatesCmd { + /// Module filter pattern (substring match by default, regex with -r) + pub module: Option, + + /// Aggregate results by module (show which modules have most duplicates) + #[arg(long)] + pub by_module: bool, + + /// Use exact source matching instead of AST matching + #[arg(long)] + pub exact: bool, + + /// Exclude macro-generated functions + #[arg(long)] + pub exclude_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for DuplicatesCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/duplicates/output.rs b/cli/src/commands/duplicates/output.rs new file mode 100644 index 0000000..d79a3fc --- /dev/null +++ b/cli/src/commands/duplicates/output.rs @@ -0,0 +1,90 @@ +use crate::output::Outputable; + +use super::execute::{DuplicatesByModuleResult, DuplicatesOutput, DuplicatesResult}; + +impl Outputable for DuplicatesResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + lines.push("Duplicate Functions".to_string()); + lines.push(String::new()); + + if self.groups.is_empty() { + lines.push("No duplicate functions found.".to_string()); + } else { + lines.push(format!( + "Found {} group(s) of duplicate(s) ({} function(s) total):", + self.total_groups, self.total_duplicates + )); + lines.push(String::new()); + + for (idx, group) in self.groups.iter().enumerate() { + // Format hash - truncate for readability + let hash_display = if group.hash.len() > 20 { + format!("{}...", &group.hash[..17]) + } else { + group.hash.clone() + }; + + lines.push(format!( + "Group {} - hash:{}... ({} function(s)):", + idx + 1, + hash_display, + group.functions.len() + )); + + for func in &group.functions { + lines.push(format!( + " {}.{}/{} L{} {}", + func.module, func.name, func.arity, func.line, func.file + )); + } + lines.push(String::new()); + } + } + + lines.join("\n") + } +} + +impl Outputable for DuplicatesByModuleResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + lines.push("Modules with Most Duplicates".to_string()); + lines.push(String::new()); + + if self.modules.is_empty() { + lines.push("No duplicate functions found.".to_string()); + } else { + lines.push(format!( + "Found {} duplicated function(s) across {} module(s):", + self.total_duplicates, self.total_modules + )); + lines.push(String::new()); + + for module in &self.modules { + lines.push(format!("{} ({} duplicates):", module.name, module.duplicate_count)); + + for dup in &module.top_duplicates { + lines.push(format!( + " {}/{} ({} copies)", + dup.name, dup.arity, dup.copy_count + )); + } + lines.push(String::new()); + } + } + + lines.join("\n") + } +} + +impl Outputable for DuplicatesOutput { + fn to_table(&self) -> String { + match self { + DuplicatesOutput::Detailed(result) => result.to_table(), + DuplicatesOutput::ByModule(result) => result.to_table(), + } + } +} diff --git a/cli/src/commands/duplicates/output_tests.rs b/cli/src/commands/duplicates/output_tests.rs new file mode 100644 index 0000000..5758593 --- /dev/null +++ b/cli/src/commands/duplicates/output_tests.rs @@ -0,0 +1,541 @@ +//! Output formatting tests for duplicates command. + +#[cfg(test)] +mod tests { + use super::super::execute::{ + DuplicateFunctionEntry, DuplicateGroup, DuplicateSummary, DuplicatesByModuleResult, + DuplicatesOutput, DuplicatesResult, ModuleDuplicates, + }; + use crate::output::{OutputFormat, Outputable}; + + #[test] + fn test_to_table_empty() { + let result = DuplicatesResult { + total_groups: 0, + total_duplicates: 0, + groups: vec![], + }; + + let output = result.to_table(); + assert!(output.contains("Duplicate Functions")); + assert!(output.contains("No duplicate functions found")); + } + + #[test] + fn test_to_table_single_group() { + let result = DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "abc123def456".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "MyApp.User".to_string(), + name: "validate".to_string(), + arity: 1, + line: 10, + file: "lib/my_app/user.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "MyApp.Post".to_string(), + name: "validate".to_string(), + arity: 1, + line: 15, + file: "lib/my_app/post.ex".to_string(), + }, + ], + }], + }; + + let output = result.to_table(); + assert!(output.contains("Duplicate Functions")); + assert!(output.contains("Found 1 group(s)")); + assert!(output.contains("MyApp.User.validate/1")); + assert!(output.contains("MyApp.Post.validate/1")); + assert!(output.contains("lib/my_app/user.ex")); + assert!(output.contains("lib/my_app/post.ex")); + } + + #[test] + fn test_to_table_multiple_groups() { + let result = DuplicatesResult { + total_groups: 2, + total_duplicates: 5, + groups: vec![ + DuplicateGroup { + hash: "hash_a".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "A".to_string(), + name: "f1".to_string(), + arity: 1, + line: 10, + file: "a.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "B".to_string(), + name: "f1".to_string(), + arity: 1, + line: 20, + file: "b.ex".to_string(), + }, + ], + }, + DuplicateGroup { + hash: "hash_b".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "C".to_string(), + name: "f2".to_string(), + arity: 2, + line: 30, + file: "c.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "D".to_string(), + name: "f2".to_string(), + arity: 2, + line: 40, + file: "d.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "E".to_string(), + name: "f2".to_string(), + arity: 2, + line: 50, + file: "e.ex".to_string(), + }, + ], + }, + ], + }; + + let output = result.to_table(); + assert!(output.contains("Found 2 group(s)")); + assert!(output.contains("5 function(s)")); + assert!(output.contains("Group 1")); + assert!(output.contains("Group 2")); + assert!(output.contains("A.f1/1")); + assert!(output.contains("C.f2/2")); + } + + #[test] + fn test_hash_truncation() { + let long_hash = "abcdefghijklmnopqrstuvwxyz1234567890"; + let result = DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: long_hash.to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "A".to_string(), + name: "f".to_string(), + arity: 0, + line: 1, + file: "a.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "B".to_string(), + name: "f".to_string(), + arity: 0, + line: 2, + file: "b.ex".to_string(), + }, + ], + }], + }; + + let output = result.to_table(); + // Hash should be truncated with "..." + assert!(output.contains("...")); + } + + #[test] + fn test_format_json() { + let result = DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "abc".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "M".to_string(), + name: "f".to_string(), + arity: 1, + line: 10, + file: "m.ex".to_string(), + }, + ], + }], + }; + + let output = result.format(OutputFormat::Json); + assert!(output.contains("total_groups")); + assert!(output.contains("total_duplicates")); + assert!(output.contains("groups")); + assert!(output.contains("\"hash\"")); + assert!(output.contains("\"functions\"")); + } + + #[test] + fn test_format_toon() { + let result = DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "abc".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "M".to_string(), + name: "f".to_string(), + arity: 1, + line: 10, + file: "m.ex".to_string(), + }, + ], + }], + }; + + let output = result.format(OutputFormat::Toon); + // Toon format should contain key parts + assert!(output.contains("total_groups")); + assert!(output.contains("1")); // count value + } + + #[test] + fn test_format_table() { + let result = DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "abc".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "M".to_string(), + name: "f".to_string(), + arity: 1, + line: 10, + file: "m.ex".to_string(), + }, + ], + }], + }; + + let output = result.format(OutputFormat::Table); + assert!(output.contains("Duplicate Functions")); + assert!(output.contains("M.f/1")); + } + + // ========================================================================= + // By-module output tests + // ========================================================================= + + #[test] + fn test_by_module_to_table_empty() { + let result = DuplicatesByModuleResult { + total_modules: 0, + total_duplicates: 0, + modules: vec![], + }; + + let output = result.to_table(); + assert!(output.contains("Modules with Most Duplicates")); + assert!(output.contains("No duplicate functions found")); + } + + #[test] + fn test_by_module_to_table_single() { + let result = DuplicatesByModuleResult { + total_modules: 1, + total_duplicates: 3, + modules: vec![ModuleDuplicates { + name: "MyApp.Utils".to_string(), + duplicate_count: 3, + top_duplicates: vec![ + DuplicateSummary { + name: "validate".to_string(), + arity: 1, + copy_count: 2, + }, + DuplicateSummary { + name: "format".to_string(), + arity: 2, + copy_count: 1, + }, + ], + }], + }; + + let output = result.to_table(); + assert!(output.contains("Modules with Most Duplicates")); + assert!(output.contains("Found 3 duplicated function(s) across 1 module(s)")); + assert!(output.contains("MyApp.Utils (3 duplicates)")); + assert!(output.contains("validate/1 (2 copies)")); + assert!(output.contains("format/2 (1 copies)")); + } + + #[test] + fn test_by_module_to_table_multiple() { + let result = DuplicatesByModuleResult { + total_modules: 2, + total_duplicates: 5, + modules: vec![ + ModuleDuplicates { + name: "MyApp.Users".to_string(), + duplicate_count: 3, + top_duplicates: vec![DuplicateSummary { + name: "validate".to_string(), + arity: 1, + copy_count: 3, + }], + }, + ModuleDuplicates { + name: "MyApp.Posts".to_string(), + duplicate_count: 2, + top_duplicates: vec![DuplicateSummary { + name: "format".to_string(), + arity: 0, + copy_count: 2, + }], + }, + ], + }; + + let output = result.to_table(); + assert!(output.contains("Found 5 duplicated function(s) across 2 module(s)")); + assert!(output.contains("MyApp.Users (3 duplicates)")); + assert!(output.contains("MyApp.Posts (2 duplicates)")); + } + + #[test] + fn test_by_module_format_json() { + let result = DuplicatesByModuleResult { + total_modules: 1, + total_duplicates: 2, + modules: vec![ModuleDuplicates { + name: "MyApp".to_string(), + duplicate_count: 2, + top_duplicates: vec![DuplicateSummary { + name: "f".to_string(), + arity: 1, + copy_count: 2, + }], + }], + }; + + let output = result.format(OutputFormat::Json); + assert!(output.contains("\"total_modules\"")); + assert!(output.contains("\"total_duplicates\"")); + assert!(output.contains("\"modules\"")); + assert!(output.contains("\"name\"")); + assert!(output.contains("\"duplicate_count\"")); + assert!(output.contains("\"top_duplicates\"")); + assert!(output.contains("\"copy_count\"")); + } + + #[test] + fn test_by_module_format_toon() { + let result = DuplicatesByModuleResult { + total_modules: 1, + total_duplicates: 2, + modules: vec![ModuleDuplicates { + name: "MyApp".to_string(), + duplicate_count: 2, + top_duplicates: vec![DuplicateSummary { + name: "f".to_string(), + arity: 1, + copy_count: 2, + }], + }], + }; + + let output = result.format(OutputFormat::Toon); + assert!(output.contains("total_modules")); + assert!(output.contains("total_duplicates")); + } + + // ========================================================================= + // DuplicatesOutput enum tests + // ========================================================================= + + #[test] + fn test_output_enum_detailed_empty() { + let result = DuplicatesOutput::Detailed(DuplicatesResult { + total_groups: 0, + total_duplicates: 0, + groups: vec![], + }); + + let output = result.to_table(); + assert!(output.contains("Duplicate Functions")); + assert!(output.contains("No duplicate functions found")); + } + + #[test] + fn test_output_enum_by_module_empty() { + let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { + total_modules: 0, + total_duplicates: 0, + modules: vec![], + }); + + let output = result.to_table(); + assert!(output.contains("Modules with Most Duplicates")); + assert!(output.contains("No duplicate functions found")); + } + + #[test] + fn test_output_enum_detailed_with_data() { + let result = DuplicatesOutput::Detailed(DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "abc123".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "MyApp.User".to_string(), + name: "validate".to_string(), + arity: 1, + line: 10, + file: "lib/user.ex".to_string(), + }, + DuplicateFunctionEntry { + module: "MyApp.Post".to_string(), + name: "validate".to_string(), + arity: 1, + line: 20, + file: "lib/post.ex".to_string(), + }, + ], + }], + }); + + // Table format + let table = result.to_table(); + assert!(table.contains("Duplicate Functions")); + assert!(table.contains("Found 1 group(s)")); + assert!(table.contains("MyApp.User.validate/1")); + assert!(table.contains("MyApp.Post.validate/1")); + + // JSON format + let json = result.format(OutputFormat::Json); + assert!(json.contains("\"total_groups\": 1")); + assert!(json.contains("\"total_duplicates\": 2")); + assert!(json.contains("\"hash\": \"abc123\"")); + assert!(json.contains("\"module\": \"MyApp.User\"")); + + // Toon format + let toon = result.format(OutputFormat::Toon); + assert!(toon.contains("total_groups")); + assert!(toon.contains("groups")); + } + + #[test] + fn test_output_enum_by_module_with_data() { + let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { + total_modules: 2, + total_duplicates: 5, + modules: vec![ + ModuleDuplicates { + name: "MyApp.Users".to_string(), + duplicate_count: 3, + top_duplicates: vec![DuplicateSummary { + name: "validate".to_string(), + arity: 1, + copy_count: 3, + }], + }, + ModuleDuplicates { + name: "MyApp.Posts".to_string(), + duplicate_count: 2, + top_duplicates: vec![DuplicateSummary { + name: "format".to_string(), + arity: 0, + copy_count: 2, + }], + }, + ], + }); + + // Table format + let table = result.to_table(); + assert!(table.contains("Modules with Most Duplicates")); + assert!(table.contains("Found 5 duplicated function(s) across 2 module(s)")); + assert!(table.contains("MyApp.Users (3 duplicates)")); + assert!(table.contains("MyApp.Posts (2 duplicates)")); + + // JSON format + let json = result.format(OutputFormat::Json); + assert!(json.contains("\"total_modules\": 2")); + assert!(json.contains("\"total_duplicates\": 5")); + assert!(json.contains("\"name\": \"MyApp.Users\"")); + assert!(json.contains("\"duplicate_count\": 3")); + + // Toon format + let toon = result.format(OutputFormat::Toon); + assert!(toon.contains("total_modules")); + assert!(toon.contains("modules")); + } + + #[test] + fn test_output_enum_detailed_json_structure() { + let result = DuplicatesOutput::Detailed(DuplicatesResult { + total_groups: 1, + total_duplicates: 2, + groups: vec![DuplicateGroup { + hash: "test_hash".to_string(), + functions: vec![ + DuplicateFunctionEntry { + module: "A".to_string(), + name: "func".to_string(), + arity: 0, + line: 1, + file: "a.ex".to_string(), + }, + ], + }], + }); + + let json = result.format(OutputFormat::Json); + // Verify JSON structure has expected fields + assert!(json.contains("\"total_groups\"")); + assert!(json.contains("\"total_duplicates\"")); + assert!(json.contains("\"groups\"")); + assert!(json.contains("\"hash\"")); + assert!(json.contains("\"functions\"")); + assert!(json.contains("\"module\"")); + assert!(json.contains("\"name\"")); + assert!(json.contains("\"arity\"")); + assert!(json.contains("\"line\"")); + assert!(json.contains("\"file\"")); + } + + #[test] + fn test_output_enum_by_module_json_structure() { + let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { + total_modules: 1, + total_duplicates: 2, + modules: vec![ModuleDuplicates { + name: "TestModule".to_string(), + duplicate_count: 2, + top_duplicates: vec![DuplicateSummary { + name: "func".to_string(), + arity: 1, + copy_count: 2, + }], + }], + }); + + let json = result.format(OutputFormat::Json); + // Verify JSON structure has expected fields + assert!(json.contains("\"total_modules\"")); + assert!(json.contains("\"total_duplicates\"")); + assert!(json.contains("\"modules\"")); + assert!(json.contains("\"name\"")); + assert!(json.contains("\"duplicate_count\"")); + assert!(json.contains("\"top_duplicates\"")); + assert!(json.contains("\"arity\"")); + assert!(json.contains("\"copy_count\"")); + } +} diff --git a/cli/src/commands/function/cli_tests.rs b/cli/src/commands/function/cli_tests.rs new file mode 100644 index 0000000..7fd81c9 --- /dev/null +++ b/cli/src/commands/function/cli_tests.rs @@ -0,0 +1,88 @@ +//! CLI parsing tests for function command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "function", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_required_arg_test! { + command: "function", + test_name: test_requires_function, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "function", + variant: Function, + test_name: test_with_module_and_function, + args: ["MyApp.Accounts", "get_user"], + field: module, + expected: "MyApp.Accounts", + } + + crate::cli_option_test! { + command: "function", + variant: Function, + test_name: test_function_name, + args: ["MyApp.Accounts", "get_user"], + field: function, + expected: "get_user", + } + + crate::cli_option_test! { + command: "function", + variant: Function, + test_name: test_with_arity, + args: ["MyApp.Accounts", "get_user", "--arity", "1"], + field: arity, + expected: Some(1), + } + + crate::cli_option_test! { + command: "function", + variant: Function, + test_name: test_with_regex, + args: ["MyApp.*", "get_.*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "function", + variant: Function, + test_name: test_with_limit, + args: ["MyApp", "foo", "--limit", "50"], + field: common.limit, + expected: 50, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "function", + variant: Function, + required_args: ["MyApp", "foo"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/function/execute.rs b/cli/src/commands/function/execute.rs new file mode 100644 index 0000000..f14fdbb --- /dev/null +++ b/cli/src/commands/function/execute.rs @@ -0,0 +1,73 @@ +use std::error::Error; + +use serde::Serialize; + +use super::FunctionCmd; +use crate::commands::Execute; +use crate::queries::function::{find_functions, FunctionSignature}; +use crate::types::ModuleGroupResult; + +/// A function signature within a module +#[derive(Debug, Clone, Serialize)] +pub struct FuncSig { + pub name: String, + pub arity: i64, + #[serde(skip_serializing_if = "String::is_empty")] + pub args: String, + #[serde(skip_serializing_if = "String::is_empty")] + pub return_type: String, +} + +impl ModuleGroupResult { + /// Build grouped result from flat FunctionSignature list + fn from_signatures( + module_pattern: String, + function_pattern: String, + signatures: Vec, + ) -> Self { + let total_items = signatures.len(); + + // Use helper to group by module + let items = crate::utils::group_by_module(signatures, |sig| { + let func_sig = FuncSig { + name: sig.name, + arity: sig.arity, + args: sig.args, + return_type: sig.return_type, + }; + // File is intentionally empty for functions because the function command + // queries the functions table which doesn't track file locations. + // File locations are available in function_locations table if needed. + (sig.module, func_sig) + }); + + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, + } + } +} + +impl Execute for FunctionCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let signatures = find_functions( + db, + &self.module, + &self.function, + self.arity, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(>::from_signatures( + self.module, + self.function, + signatures, + )) + } +} diff --git a/cli/src/commands/function/execute_tests.rs b/cli/src/commands/function/execute_tests.rs new file mode 100644 index 0000000..1e29aaf --- /dev/null +++ b/cli/src/commands/function/execute_tests.rs @@ -0,0 +1,160 @@ +//! Execute tests for function command. + +#[cfg(test)] +mod tests { + use super::super::FunctionCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: type_signatures, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // MyApp.Accounts has 2 get_user functions (arity 1 and 2) + crate::execute_test! { + test_name: test_function_exact_match, + fixture: populated_db, + cmd: FunctionCmd { + module: "MyApp.Accounts".to_string(), + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2); + assert_eq!(result.items.len(), 1); + assert_eq!(result.items[0].entries.len(), 2); + }, + } + + crate::execute_test! { + test_name: test_function_with_arity, + fixture: populated_db, + cmd: FunctionCmd { + module: "MyApp.Accounts".to_string(), + function: "get_user".to_string(), + arity: Some(1), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 1); + let func = &result.items[0].entries[0]; + assert_eq!(func.arity, 1); + assert_eq!(func.args, "integer()"); + assert_eq!(func.return_type, "User.t() | nil"); + }, + } + + // Functions containing "user": get_user/1, get_user/2, list_users, create_user = 4 + crate::execute_test! { + test_name: test_function_regex_match, + fixture: populated_db, + cmd: FunctionCmd { + module: "MyApp\\..*".to_string(), + function: ".*user.*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 4); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_function_no_match, + fixture: populated_db, + cmd: FunctionCmd { + module: "NonExistent".to_string(), + function: "foo".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: items, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_function_with_project_filter, + fixture: populated_db, + cmd: FunctionCmd { + module: "MyApp.Accounts".to_string(), + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.items.len(), 1); + assert_eq!(result.items[0].name, "MyApp.Accounts"); + }, + } + + crate::execute_test! { + test_name: test_function_with_limit, + fixture: populated_db, + cmd: FunctionCmd { + module: "MyApp\\..*".to_string(), + function: ".*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 2, + }, + }, + assertions: |result| { + // Limit applies to raw results before grouping + assert_eq!(result.total_items, 2); + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: FunctionCmd, + cmd: FunctionCmd { + module: "MyApp".to_string(), + function: "foo".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/function/mod.rs b/cli/src/commands/function/mod.rs new file mode 100644 index 0000000..a2b21e5 --- /dev/null +++ b/cli/src/commands/function/mod.rs @@ -0,0 +1,43 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Show function signature (args, return type) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search function MyApp.Accounts get_user # Show signature + code_search function MyApp.Accounts get_user -a 1 # Specific arity + code_search function -r 'MyApp\\..*' 'get_.*' # Regex matching +")] +pub struct FunctionCmd { + /// Module name (exact match or pattern with --regex) + pub module: String, + + /// Function name (exact match or pattern with --regex) + pub function: String, + + /// Function arity (optional, matches all arities if not specified) + #[arg(short, long)] + pub arity: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for FunctionCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/function/output.rs b/cli/src/commands/function/output.rs new file mode 100644 index 0000000..dffa742 --- /dev/null +++ b/cli/src/commands/function/output.rs @@ -0,0 +1,41 @@ +//! Output formatting for function command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::FuncSig; + +impl TableFormatter for ModuleGroupResult { + type Entry = FuncSig; + + fn format_header(&self) -> String { + let function_pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + format!("Function: {}.{}", self.module_pattern, function_pattern) + } + + fn format_empty_message(&self) -> String { + "No functions found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} signature(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, func: &FuncSig, _module: &str, _file: &str) -> String { + format!("{}/{}", func.name, func.arity) + } + + fn format_entry_details(&self, func: &FuncSig, _module: &str, _file: &str) -> Vec { + let mut details = Vec::new(); + if !func.args.is_empty() { + details.push(format!("args: {}", func.args)); + } + if !func.return_type.is_empty() { + details.push(format!("returns: {}", func.return_type)); + } + details + } +} diff --git a/cli/src/commands/function/output_tests.rs b/cli/src/commands/function/output_tests.rs new file mode 100644 index 0000000..86aec7f --- /dev/null +++ b/cli/src/commands/function/output_tests.rs @@ -0,0 +1,152 @@ +//! Output formatting tests for function command. + +#[cfg(test)] +mod tests { + use super::super::execute::FuncSig; + use crate::types::{ModuleGroupResult, ModuleGroup}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Function: MyApp.Accounts.get_user + +No functions found."; + + const SINGLE_TABLE: &str = "\ +Function: MyApp.Accounts.get_user + +Found 1 signature(s) in 1 module(s): + +MyApp.Accounts: + get_user/1 + args: integer() + returns: User.t() | nil"; + + const MULTIPLE_TABLE: &str = "\ +Function: MyApp.Accounts.get_user + +Found 2 signature(s) in 1 module(s): + +MyApp.Accounts: + get_user/1 + args: integer() + returns: User.t() | nil + get_user/2 + args: integer(), keyword() + returns: User.t() | nil"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: Some("get_user".to_string()), + total_items: 0, + items: vec![], + } + } + + #[fixture] + fn single_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: Some("get_user".to_string()), + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: String::new(), + entries: vec![FuncSig { + name: "get_user".to_string(), + arity: 1, + args: "integer()".to_string(), + return_type: "User.t() | nil".to_string(), + }], + function_count: None, + }], + } + } + + #[fixture] + fn multiple_result() -> ModuleGroupResult { + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: Some("get_user".to_string()), + total_items: 2, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: String::new(), + entries: vec![ + FuncSig { + name: "get_user".to_string(), + arity: 1, + args: "integer()".to_string(), + return_type: "User.t() | nil".to_string(), + }, + FuncSig { + name: "get_user".to_string(), + arity: 2, + args: "integer(), keyword()".to_string(), + return_type: "User.t() | nil".to_string(), + }, + ], + function_count: None, + }], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: ModuleGroupResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("function", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("function", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleGroupResult, + expected: crate::test_utils::load_output_fixture("function", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/god_modules/execute.rs b/cli/src/commands/god_modules/execute.rs new file mode 100644 index 0000000..cf4ee0d --- /dev/null +++ b/cli/src/commands/god_modules/execute.rs @@ -0,0 +1,164 @@ +use std::error::Error; + +use serde::Serialize; + +use super::GodModulesCmd; +use crate::commands::Execute; +use crate::queries::hotspots::{find_hotspots, get_function_counts, get_module_loc, HotspotKind}; +use crate::types::{ModuleCollectionResult, ModuleGroup}; + +/// A single god module entry +#[derive(Debug, Clone, Serialize)] +pub struct GodModuleEntry { + pub function_count: i64, + pub loc: i64, + pub incoming: i64, + pub outgoing: i64, + pub total: i64, +} + +impl Execute for GodModulesCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + // Get function counts for all modules + let func_counts = get_function_counts( + db, + &self.common.project, + self.module.as_deref(), + self.common.regex, + )?; + + // Get lines of code per module + let module_loc = get_module_loc( + db, + &self.common.project, + self.module.as_deref(), + self.common.regex, + )?; + + // Get hotspot data (incoming/outgoing calls per function) + let hotspots = find_hotspots( + db, + HotspotKind::Total, + self.module.as_deref(), + &self.common.project, + self.common.regex, + u32::MAX, // Get all hotspots to aggregate connectivity + false, // Don't exclude generated functions + false, // Don't require outgoing calls + )?; + + // Aggregate connectivity (incoming/outgoing) per module + let mut module_connectivity: std::collections::HashMap = + std::collections::HashMap::new(); + + for hotspot in hotspots { + let entry = module_connectivity + .entry(hotspot.module) + .or_insert((0, 0)); + entry.0 += hotspot.incoming; + entry.1 += hotspot.outgoing; + } + + // Build god modules: filter by thresholds and sort by total connectivity + // Tuple: (module_name, func_count, loc, incoming, outgoing) + let mut god_modules: Vec<(String, i64, i64, i64, i64)> = Vec::new(); + + for (module_name, func_count) in func_counts { + // Apply function count threshold + if func_count < self.min_functions { + continue; + } + + // Get LoC for this module + let loc = module_loc.get(&module_name).copied().unwrap_or(0); + + // Apply LoC threshold if set + if loc < self.min_loc { + continue; + } + + // Get connectivity for this module + let (incoming, outgoing) = module_connectivity + .get(&module_name) + .copied() + .unwrap_or((0, 0)); + let total = incoming + outgoing; + + // Apply total connectivity threshold + if total < self.min_total { + continue; + } + + god_modules.push((module_name, func_count, loc, incoming, outgoing)); + } + + // Sort by total connectivity (descending) + god_modules.sort_by(|a, b| { + let total_a = a.3 + a.4; + let total_b = b.3 + b.4; + total_b.cmp(&total_a) + }); + + // Apply limit + let limit = self.common.limit as usize; + god_modules.truncate(limit); + + // Convert to ModuleGroup entries + let total_items = god_modules.len(); + let items: Vec> = god_modules + .into_iter() + .map(|(module_name, func_count, loc, incoming, outgoing)| { + let total = incoming + outgoing; + ModuleGroup { + name: module_name, + file: String::new(), + entries: vec![GodModuleEntry { + function_count: func_count, + loc, + incoming, + outgoing, + total, + }], + function_count: Some(func_count), + } + }) + .collect(); + + Ok(ModuleCollectionResult { + module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), + function_pattern: None, + kind_filter: Some("god".to_string()), + name_filter: None, + total_items, + items, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_god_modules_cmd_structure() { + // Test that GodModulesCmd is created correctly + let cmd = GodModulesCmd { + min_functions: 30, + min_loc: 500, + min_total: 15, + module: Some("MyApp".to_string()), + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 20, + }, + }; + + assert_eq!(cmd.min_functions, 30); + assert_eq!(cmd.min_loc, 500); + assert_eq!(cmd.min_total, 15); + assert_eq!(cmd.module, Some("MyApp".to_string())); + } +} diff --git a/cli/src/commands/god_modules/mod.rs b/cli/src/commands/god_modules/mod.rs new file mode 100644 index 0000000..809b4f6 --- /dev/null +++ b/cli/src/commands/god_modules/mod.rs @@ -0,0 +1,51 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find god modules - modules with high function count and high connectivity +/// +/// God modules are those with many functions and high incoming/outgoing call counts, +/// indicating they have too many responsibilities. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search god-modules # Find all god modules + code_search god-modules MyApp.Core # Filter to MyApp.Core namespace + code_search god-modules --min-functions 30 # With minimum 30 functions + code_search god-modules --min-loc 500 # With minimum 500 lines of code + code_search god-modules --min-total 15 # With minimum 15 total connectivity + code_search god-modules -l 20 # Show top 20 god modules +")] +pub struct GodModulesCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Minimum function count to be considered a god module + #[arg(long, default_value = "20")] + pub min_functions: i64, + + /// Minimum lines of code to be considered a god module + #[arg(long, default_value = "0")] + pub min_loc: i64, + + /// Minimum total connectivity (incoming + outgoing) to be considered a god module + #[arg(long, default_value = "10")] + pub min_total: i64, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for GodModulesCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/god_modules/output.rs b/cli/src/commands/god_modules/output.rs new file mode 100644 index 0000000..678d811 --- /dev/null +++ b/cli/src/commands/god_modules/output.rs @@ -0,0 +1,55 @@ +//! Output formatting for god modules command results. + +use super::execute::GodModuleEntry; +use crate::output::TableFormatter; +use crate::types::ModuleCollectionResult; + +impl TableFormatter for ModuleCollectionResult { + type Entry = GodModuleEntry; + + fn format_header(&self) -> String { + "God Modules".to_string() + } + + fn format_empty_message(&self) -> String { + "No god modules found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} god module(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_module_header_with_entries( + &self, + module_name: &str, + _module_file: &str, + entries: &[GodModuleEntry], + ) -> String { + if let Some(entry) = entries.first() { + format!( + "{}: (funcs: {}, loc: {}, in: {}, out: {}, total: {})", + module_name, entry.function_count, entry.loc, entry.incoming, entry.outgoing, entry.total + ) + } else { + format!("{}:", module_name) + } + } + + fn format_entry(&self, _entry: &GodModuleEntry, _module: &str, _file: &str) -> String { + // For god modules, we don't show individual entries since each module has only one entry + // The module header already shows all the stats + String::new() + } + + fn blank_before_module(&self) -> bool { + true + } + + fn blank_after_summary(&self) -> bool { + false + } +} diff --git a/cli/src/commands/hotspots/cli_tests.rs b/cli/src/commands/hotspots/cli_tests.rs new file mode 100644 index 0000000..6ff3c65 --- /dev/null +++ b/cli/src/commands/hotspots/cli_tests.rs @@ -0,0 +1,133 @@ +//! CLI parsing tests for hotspots command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use crate::queries::hotspots::HotspotKind; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + // Test default values + crate::cli_defaults_test! { + command: "hotspots", + variant: Hotspots, + required_args: [], + defaults: { + common.project: "default", + common.regex: false, + common.limit: 100, + exclude_generated: false, + }, + } + + // Test positional module argument + crate::cli_option_test! { + command: "hotspots", + variant: Hotspots, + test_name: test_with_module, + args: ["MyApp"], + field: module, + expected: Some("MyApp".to_string()), + } + + crate::cli_option_test! { + command: "hotspots", + variant: Hotspots, + test_name: test_with_project, + args: ["--project", "my_app"], + field: common.project, + expected: "my_app", + } + + crate::cli_option_test! { + command: "hotspots", + variant: Hotspots, + test_name: test_with_regex, + args: ["MyApp\\..*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "hotspots", + variant: Hotspots, + test_name: test_with_limit, + args: ["--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_option_test! { + command: "hotspots", + variant: Hotspots, + test_name: test_with_exclude_generated, + args: ["--exclude-generated"], + field: exclude_generated, + expected: true, + } + + // Test limit validation + crate::cli_limit_tests! { + command: "hotspots", + variant: Hotspots, + required_args: [], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Kind option tests + // ========================================================================= + + #[rstest] + fn test_kind_default_is_incoming() { + let args = Args::try_parse_from(["code_search", "hotspots"]).unwrap(); + match args.command { + crate::commands::Command::Hotspots(cmd) => { + assert!(matches!(cmd.kind, HotspotKind::Incoming)); + } + _ => panic!("Expected Hotspots command"), + } + } + + #[rstest] + fn test_kind_outgoing() { + let args = + Args::try_parse_from(["code_search", "hotspots", "--kind", "outgoing"]).unwrap(); + match args.command { + crate::commands::Command::Hotspots(cmd) => { + assert!(matches!(cmd.kind, HotspotKind::Outgoing)); + } + _ => panic!("Expected Hotspots command"), + } + } + + #[rstest] + fn test_kind_total() { + let args = Args::try_parse_from(["code_search", "hotspots", "--kind", "total"]).unwrap(); + match args.command { + crate::commands::Command::Hotspots(cmd) => { + assert!(matches!(cmd.kind, HotspotKind::Total)); + } + _ => panic!("Expected Hotspots command"), + } + } + + #[rstest] + fn test_kind_ratio() { + let args = Args::try_parse_from(["code_search", "hotspots", "--kind", "ratio"]).unwrap(); + match args.command { + crate::commands::Command::Hotspots(cmd) => { + assert!(matches!(cmd.kind, HotspotKind::Ratio)); + } + _ => panic!("Expected Hotspots command"), + } + } +} diff --git a/cli/src/commands/hotspots/execute.rs b/cli/src/commands/hotspots/execute.rs new file mode 100644 index 0000000..5d8ca38 --- /dev/null +++ b/cli/src/commands/hotspots/execute.rs @@ -0,0 +1,142 @@ +use std::error::Error; + +use serde::Serialize; + +use super::HotspotsCmd; +use crate::commands::Execute; +use crate::output::Outputable; +use crate::queries::hotspots::find_hotspots; + +/// A function hotspot entry +#[derive(Debug, Clone, Serialize)] +pub struct FunctionHotspotEntry { + pub module: String, + pub function: String, + pub incoming: i64, + pub outgoing: i64, + pub total: i64, + pub ratio: f64, +} + +/// Result type for hotspots command +#[derive(Debug, Serialize)] +pub struct HotspotsResult { + pub kind: String, + pub total_items: usize, + pub entries: Vec, +} + +impl Outputable for HotspotsResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + lines.push(format!("Hotspots ({})", self.kind)); + lines.push(String::new()); + + if self.entries.is_empty() { + lines.push("No hotspots found.".to_string()); + return lines.join("\n"); + } + + let item_word = if self.total_items == 1 { + "function" + } else { + "functions" + }; + lines.push(format!("Found {} {}:", self.total_items, item_word)); + lines.push(String::new()); + + // Calculate column widths for alignment + let name_width = self + .entries + .iter() + .map(|e| e.module.len() + 1 + e.function.len()) + .max() + .unwrap_or(0); + let in_width = self + .entries + .iter() + .map(|e| e.incoming.to_string().len()) + .max() + .unwrap_or(0); + let out_width = self + .entries + .iter() + .map(|e| e.outgoing.to_string().len()) + .max() + .unwrap_or(0); + let total_width = self + .entries + .iter() + .map(|e| e.total.to_string().len()) + .max() + .unwrap_or(0); + + for entry in &self.entries { + let name = format!("{}.{}", entry.module, entry.function); + let ratio_str = if entry.ratio >= 9999.0 { + "∞".to_string() + } else { + format!("{:.2}", entry.ratio) + }; + lines.push(format!( + "{:in_width$} in {:>out_width$} out {:>total_width$} total {:>6} ratio", + name, + entry.incoming, + entry.outgoing, + entry.total, + ratio_str, + name_width = name_width, + in_width = in_width, + out_width = out_width, + total_width = total_width, + )); + } + + lines.join("\n") + } +} + +impl Execute for HotspotsCmd { + type Output = HotspotsResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let hotspots = find_hotspots( + db, + self.kind, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.common.limit, + self.exclude_generated, + false, // Don't require outgoing calls + )?; + + let kind_str = match self.kind { + crate::queries::hotspots::HotspotKind::Incoming => "incoming", + crate::queries::hotspots::HotspotKind::Outgoing => "outgoing", + crate::queries::hotspots::HotspotKind::Total => "total", + crate::queries::hotspots::HotspotKind::Ratio => "ratio", + }; + + let entries: Vec = hotspots + .into_iter() + .map(|hotspot| FunctionHotspotEntry { + module: hotspot.module, + function: hotspot.function, + incoming: hotspot.incoming, + outgoing: hotspot.outgoing, + total: hotspot.total, + ratio: hotspot.ratio, + }) + .collect(); + + let total_items = entries.len(); + + Ok(HotspotsResult { + kind: kind_str.to_string(), + total_items, + entries, + }) + } +} diff --git a/cli/src/commands/hotspots/execute_tests.rs b/cli/src/commands/hotspots/execute_tests.rs new file mode 100644 index 0000000..38af50b --- /dev/null +++ b/cli/src/commands/hotspots/execute_tests.rs @@ -0,0 +1,170 @@ +//! Execute tests for hotspots command. + +#[cfg(test)] +mod tests { + use super::super::HotspotsCmd; + use crate::commands::CommonArgs; + use crate::commands::Execute; + use crate::queries::hotspots::HotspotKind; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + #[rstest] + fn test_hotspots_incoming(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Incoming, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + assert_eq!(result.kind, "incoming"); + assert!(!result.entries.is_empty()); + } + + #[rstest] + fn test_hotspots_outgoing(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Outgoing, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + assert_eq!(result.kind, "outgoing"); + assert!(!result.entries.is_empty()); + } + + #[rstest] + fn test_hotspots_total(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Total, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + assert_eq!(result.kind, "total"); + assert!(!result.entries.is_empty()); + } + + #[rstest] + fn test_hotspots_ratio(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Ratio, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + assert_eq!(result.kind, "ratio"); + assert!(!result.entries.is_empty()); + // All entries should have a ratio value + assert!(result.entries.iter().all(|e| e.ratio >= 0.0)); + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + #[rstest] + fn test_hotspots_with_module_filter(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: Some("Accounts".to_string()), + kind: HotspotKind::Incoming, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + // All entries should have Accounts in the module name + assert!(result.entries.iter().all(|e| e.module.contains("Accounts"))); + } + + #[rstest] + fn test_hotspots_with_limit(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Incoming, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 2, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + assert!(result.entries.len() <= 2); + } + + #[rstest] + fn test_hotspots_exclude_generated(populated_db: cozo::DbInstance) { + let cmd = HotspotsCmd { + module: None, + kind: HotspotKind::Incoming, + exclude_generated: true, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }; + let result = cmd.execute(&populated_db).expect("Execute should succeed"); + + // With exclude_generated, generated functions should be filtered out + // Result may or may not be empty depending on test data + assert_eq!(result.kind, "incoming"); + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: HotspotsCmd, + cmd: HotspotsCmd { + module: None, + kind: HotspotKind::Incoming, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 20, + }, + }, + } +} diff --git a/cli/src/commands/hotspots/mod.rs b/cli/src/commands/hotspots/mod.rs new file mode 100644 index 0000000..7dc4ad7 --- /dev/null +++ b/cli/src/commands/hotspots/mod.rs @@ -0,0 +1,56 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; +use crate::queries::hotspots::HotspotKind; + +/// Find functions with the most incoming/outgoing calls +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search hotspots # Most called functions (incoming) + code_search hotspots -k outgoing # Functions that call many others + code_search hotspots -k total # Highest total connections + code_search hotspots -k ratio # Boundary functions (high incoming/outgoing ratio) + code_search hotspots MyApp -l 10 # Top 10 in MyApp namespace + code_search hotspots --exclude-generated # Exclude macro-generated functions + + # Find wide functions (high fan-out): + code_search hotspots -k outgoing -l 20 # Top 20 functions calling many others + + # Find deep functions (high fan-in): + code_search hotspots -k incoming -l 20 # Top 20 most-called functions + + # Find boundary functions (many callers, few dependencies): + code_search hotspots -k ratio -l 20 # Top 20 boundary functions")] +pub struct HotspotsCmd { + /// Module pattern to filter results (substring match by default, regex with --regex) + pub module: Option, + + /// Type of hotspots to find + #[arg(short, long, value_enum, default_value_t = HotspotKind::Incoming)] + pub kind: HotspotKind, + + /// Exclude macro-generated functions + #[arg(long)] + pub exclude_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for HotspotsCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/hotspots/output.rs b/cli/src/commands/hotspots/output.rs new file mode 100644 index 0000000..2bff26c --- /dev/null +++ b/cli/src/commands/hotspots/output.rs @@ -0,0 +1,4 @@ +//! Output formatting for hotspots command results. + +// Output formatting is now handled directly in execute.rs via the Outputable trait +// implementations for FunctionHotspotsResult and ModuleHotspotsResult. diff --git a/cli/src/commands/hotspots/output_tests.rs b/cli/src/commands/hotspots/output_tests.rs new file mode 100644 index 0000000..eaba383 --- /dev/null +++ b/cli/src/commands/hotspots/output_tests.rs @@ -0,0 +1,153 @@ +//! Output formatting tests for hotspots command. + +#[cfg(test)] +mod tests { + use super::super::execute::{FunctionHotspotEntry, HotspotsResult}; + use crate::output::{OutputFormat, Outputable}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Hotspots (incoming) + +No hotspots found."; + + const SINGLE_TABLE: &str = "\ +Hotspots (total) + +Found 1 function: + +MyApp.Accounts.get_user 3 in 1 out 4 total 0.25 ratio"; + + const MULTIPLE_TABLE: &str = "\ +Hotspots (incoming) + +Found 2 functions: + +MyApp.Accounts.get_user 10 in 2 out 12 total 0.17 ratio +MyApp.Users.create 5 in 3 out 8 total 0.38 ratio"; + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> HotspotsResult { + HotspotsResult { + kind: "incoming".to_string(), + total_items: 0, + entries: vec![], + } + } + + #[fixture] + fn single_result() -> HotspotsResult { + HotspotsResult { + kind: "total".to_string(), + total_items: 1, + entries: vec![FunctionHotspotEntry { + module: "MyApp.Accounts".to_string(), + function: "get_user".to_string(), + incoming: 3, + outgoing: 1, + total: 4, + ratio: 0.25, + }], + } + } + + #[fixture] + fn multiple_result() -> HotspotsResult { + HotspotsResult { + kind: "incoming".to_string(), + total_items: 2, + entries: vec![ + FunctionHotspotEntry { + module: "MyApp.Accounts".to_string(), + function: "get_user".to_string(), + incoming: 10, + outgoing: 2, + total: 12, + ratio: 0.17, + }, + FunctionHotspotEntry { + module: "MyApp.Users".to_string(), + function: "create".to_string(), + incoming: 5, + outgoing: 3, + total: 8, + ratio: 0.38, + }, + ], + } + } + + // ========================================================================= + // Table format tests + // ========================================================================= + + #[rstest] + fn test_to_table_empty(empty_result: HotspotsResult) { + let output = empty_result.to_table(); + assert_eq!(output, EMPTY_TABLE); + } + + #[rstest] + fn test_to_table_single(single_result: HotspotsResult) { + let output = single_result.to_table(); + assert_eq!(output, SINGLE_TABLE); + } + + #[rstest] + fn test_to_table_multiple(multiple_result: HotspotsResult) { + let output = multiple_result.to_table(); + assert_eq!(output, MULTIPLE_TABLE); + } + + // ========================================================================= + // JSON format tests + // ========================================================================= + + #[rstest] + fn test_format_json(single_result: HotspotsResult) { + let output = single_result.format(OutputFormat::Json); + assert!(output.contains("\"kind\": \"total\"")); + assert!(output.contains("\"total_items\": 1")); + assert!(output.contains("\"entries\"")); + assert!(output.contains("\"module\": \"MyApp.Accounts\"")); + assert!(output.contains("\"function\": \"get_user\"")); + assert!(output.contains("\"incoming\": 3")); + assert!(output.contains("\"outgoing\": 1")); + assert!(output.contains("\"total\": 4")); + } + + #[rstest] + fn test_format_json_empty(empty_result: HotspotsResult) { + let output = empty_result.format(OutputFormat::Json); + assert!(output.contains("\"kind\": \"incoming\"")); + assert!(output.contains("\"total_items\": 0")); + assert!(output.contains("\"entries\": []")); + } + + // ========================================================================= + // Toon format tests + // ========================================================================= + + #[rstest] + fn test_format_toon(single_result: HotspotsResult) { + let output = single_result.format(OutputFormat::Toon); + assert!(output.contains("kind")); + assert!(output.contains("total_items")); + assert!(output.contains("entries")); + } + + #[rstest] + fn test_format_toon_empty(empty_result: HotspotsResult) { + let output = empty_result.format(OutputFormat::Toon); + assert!(output.contains("kind")); + assert!(output.contains("entries")); + } +} diff --git a/cli/src/commands/import/cli_tests.rs b/cli/src/commands/import/cli_tests.rs new file mode 100644 index 0000000..2d1dca0 --- /dev/null +++ b/cli/src/commands/import/cli_tests.rs @@ -0,0 +1,76 @@ +//! CLI parsing tests for import command. +//! +//! Note: Import command has special file existence validation that requires +//! fixtures with temp files, so these tests remain as regular tests. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::{fixture, rstest}; + use std::fs::File; + use std::path::PathBuf; + use tempfile::{tempdir, TempDir}; + + #[fixture] + fn temp_file() -> (TempDir, PathBuf) { + let dir = tempdir().unwrap(); + let path = dir.path().join("test.json"); + File::create(&path).unwrap(); + (dir, path) + } + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + crate::cli_required_arg_test! { + command: "import", + test_name: test_requires_file, + required_arg: "--file", + } + + // ========================================================================= + // Edge case tests (file validation, global --db flag) + // ========================================================================= + + #[rstest] + fn test_file_must_exist() { + let result = + Args::try_parse_from(["code_search", "import", "--file", "nonexistent_file.json"]); + assert!(result.is_err()); + assert!(result.unwrap_err().to_string().contains("File not found")); + } + + #[rstest] + fn test_with_existing_file(temp_file: (TempDir, PathBuf)) { + let (_dir, path) = temp_file; + let result = + Args::try_parse_from(["code_search", "import", "--file", path.to_str().unwrap()]); + assert!(result.is_ok()); + } + + #[rstest] + fn test_db_is_optional(temp_file: (TempDir, PathBuf)) { + let (_dir, path) = temp_file; + let args = + Args::try_parse_from(["code_search", "import", "--file", path.to_str().unwrap()]) + .unwrap(); + assert_eq!(args.db, None); + } + + #[rstest] + fn test_db_can_be_overridden(temp_file: (TempDir, PathBuf)) { + let (_dir, path) = temp_file; + let args = Args::try_parse_from([ + "code_search", + "--db", + "/custom/path.db", + "import", + "--file", + path.to_str().unwrap(), + ]) + .unwrap(); + assert_eq!(args.db, Some(PathBuf::from("/custom/path.db"))); + } +} diff --git a/cli/src/commands/import/execute.rs b/cli/src/commands/import/execute.rs new file mode 100644 index 0000000..2bfe0dd --- /dev/null +++ b/cli/src/commands/import/execute.rs @@ -0,0 +1,247 @@ +use std::error::Error; +use std::fs; + +use cozo::DbInstance; + +use super::ImportCmd; +use crate::commands::Execute; +use crate::queries::import::{clear_project_data, import_graph, ImportError, ImportResult}; +use crate::queries::import_models::CallGraph; + +impl Execute for ImportCmd { + type Output = ImportResult; + + fn execute(self, db: &DbInstance) -> Result> { + // Read and parse call graph + let content = fs::read_to_string(&self.file).map_err(|e| ImportError::FileReadFailed { + path: self.file.display().to_string(), + message: e.to_string(), + })?; + + let graph: CallGraph = + serde_json::from_str(&content).map_err(|e| ImportError::JsonParseFailed { + message: e.to_string(), + })?; + + // Clear existing data if requested + if self.clear { + clear_project_data(db, &self.project)?; + } + + // Import data + let mut result = import_graph(db, &self.project, &graph)?; + result.cleared = self.clear; + + Ok(result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::db::open_db; + use rstest::{fixture, rstest}; + use std::io::Write; + use tempfile::NamedTempFile; + + fn sample_call_graph_json() -> &'static str { + r#"{ + "structs": { + "MyApp.User": { + "fields": [ + {"default": "nil", "field": "name", "required": true, "inferred_type": "binary()"}, + {"default": "0", "field": "age", "required": false, "inferred_type": "integer()"} + ] + } + }, + "function_locations": { + "MyApp.Accounts": { + "get_user/1:10": { + "name": "get_user", + "arity": 1, + "file": "lib/my_app/accounts.ex", + "column": 7, + "kind": "def", + "line": 10, + "start_line": 10, + "end_line": 15, + "pattern": "id", + "guard": null, + "source_sha": "", + "ast_sha": "" + } + } + }, + "calls": [ + { + "caller": { + "function": "get_user/1", + "line": 12, + "module": "MyApp.Accounts", + "file": "lib/my_app/accounts.ex", + "column": 5 + }, + "type": "remote", + "callee": { + "arity": 2, + "function": "get", + "module": "MyApp.Repo" + } + } + ], + "specs": { + "MyApp.Accounts": [ + { + "arity": 1, + "name": "get_user", + "line": 9, + "kind": "spec", + "clauses": [ + {"full": "@spec get_user(integer()) :: dynamic()", "input_strings": ["integer()"], "return_strings": ["dynamic()"]} + ] + } + ] + } + }"# + } + + fn create_temp_json_file(content: &str) -> NamedTempFile { + let mut file = NamedTempFile::new().expect("Failed to create temp file"); + file.write_all(content.as_bytes()) + .expect("Failed to write temp file"); + file + } + + #[fixture] + fn json_file() -> NamedTempFile { + create_temp_json_file(sample_call_graph_json()) + } + + #[fixture] + fn db_file() -> NamedTempFile { + NamedTempFile::new().expect("Failed to create temp db file") + } + + #[fixture] + fn import_result(json_file: NamedTempFile, db_file: NamedTempFile) -> ImportResult { + let cmd = ImportCmd { + file: json_file.path().to_path_buf(), + project: "test_project".to_string(), + clear: false, + }; + let db = open_db(db_file.path()).expect("Failed to open db"); + cmd.execute(&db).expect("Import should succeed") + } + + #[rstest] + fn test_import_creates_schemas(import_result: ImportResult) { + assert!(!import_result.schemas.created.is_empty() || !import_result.schemas.already_existed.is_empty()); + } + + #[rstest] + fn test_import_modules(import_result: ImportResult) { + assert_eq!(import_result.modules_imported, 2); // MyApp.Accounts + MyApp.User (from structs) + } + + #[rstest] + fn test_import_functions(import_result: ImportResult) { + assert_eq!(import_result.functions_imported, 1); // get_user/1 + } + + #[rstest] + fn test_import_calls(import_result: ImportResult) { + assert_eq!(import_result.calls_imported, 1); + } + + #[rstest] + fn test_import_structs(import_result: ImportResult) { + assert_eq!(import_result.structs_imported, 2); // 2 fields in MyApp.User + } + + #[rstest] + fn test_import_function_locations(import_result: ImportResult) { + assert_eq!(import_result.function_locations_imported, 1); + } + + #[rstest] + fn test_import_with_clear_flag(json_file: NamedTempFile, db_file: NamedTempFile) { + // First import + let cmd1 = ImportCmd { + file: json_file.path().to_path_buf(), + project: "test_project".to_string(), + clear: false, + }; + let db = open_db(db_file.path()).expect("Failed to open db"); + cmd1.execute(&db) + .expect("First import should succeed"); + + // Second import with clear + let cmd2 = ImportCmd { + file: json_file.path().to_path_buf(), + project: "test_project".to_string(), + clear: true, + }; + let result = cmd2 + .execute(&db) + .expect("Second import should succeed"); + + assert!(result.cleared); + assert_eq!(result.modules_imported, 2); + } + + #[rstest] + fn test_import_empty_graph(db_file: NamedTempFile) { + let empty_json = r#"{ + "structs": {}, + "function_locations": {}, + "calls": [], + "type_signatures": {} + }"#; + + let json_file = create_temp_json_file(empty_json); + + let cmd = ImportCmd { + file: json_file.path().to_path_buf(), + project: "test_project".to_string(), + clear: false, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db).expect("Import should succeed"); + + assert_eq!(result.modules_imported, 0); + assert_eq!(result.functions_imported, 0); + assert_eq!(result.calls_imported, 0); + assert_eq!(result.structs_imported, 0); + assert_eq!(result.function_locations_imported, 0); + } + + #[rstest] + fn test_import_invalid_json_fails(db_file: NamedTempFile) { + let invalid_json = "{ not valid json }"; + let json_file = create_temp_json_file(invalid_json); + + let cmd = ImportCmd { + file: json_file.path().to_path_buf(), + project: "test_project".to_string(), + clear: false, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db); + assert!(result.is_err()); + } + + #[rstest] + fn test_import_nonexistent_file_fails(db_file: NamedTempFile) { + let cmd = ImportCmd { + file: "/nonexistent/path/call_graph.json".into(), + project: "test_project".to_string(), + clear: false, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/import/mod.rs b/cli/src/commands/import/mod.rs new file mode 100644 index 0000000..75d43c6 --- /dev/null +++ b/cli/src/commands/import/mod.rs @@ -0,0 +1,50 @@ +mod cli_tests; +mod execute; +mod output; +mod output_tests; + +use std::error::Error; +use std::path::PathBuf; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, Execute}; +use crate::output::{OutputFormat, Outputable}; + +const DEFAULT_PROJECT: &str = "default"; + +fn validate_file_exists(s: &str) -> Result { + let path = PathBuf::from(s); + if path.exists() { + Ok(path) + } else { + Err(format!("File not found: {}", path.display())) + } +} + +/// Import a call graph JSON file into the database +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search import -f call_graph.json # Import with default project name + code_search import -f cg.json -p my_app # Import into 'my_app' project + code_search import -f cg.json --clear # Clear DB before importing")] +pub struct ImportCmd { + /// Path to the call graph JSON file + #[arg(short, long, value_parser = validate_file_exists)] + pub file: PathBuf, + /// Project name for namespacing (allows multiple projects in same DB) + #[arg(short, long, default_value = DEFAULT_PROJECT)] + pub project: String, + /// Clear all existing data before import (or just project data if --project is set) + #[arg(long, default_value_t = false)] + pub clear: bool, +} + +impl CommandRunner for ImportCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/import/output.rs b/cli/src/commands/import/output.rs new file mode 100644 index 0000000..1ab6ed4 --- /dev/null +++ b/cli/src/commands/import/output.rs @@ -0,0 +1,32 @@ +//! Output formatting for import command results. + +use crate::output::Outputable; +use crate::queries::import::ImportResult; + +impl Outputable for ImportResult { + fn to_table(&self) -> String { + let mut output = String::new(); + + if self.cleared { + output.push_str("Cleared existing project data.\n\n"); + } + + output.push_str("Import Summary:\n"); + output.push_str(&format!(" Modules: {}\n", self.modules_imported)); + output.push_str(&format!(" Functions: {}\n", self.functions_imported)); + output.push_str(&format!(" Calls: {}\n", self.calls_imported)); + output.push_str(&format!(" Structs: {}\n", self.structs_imported)); + output.push_str(&format!(" Locations: {}\n", self.function_locations_imported)); + output.push_str(&format!(" Specs: {}\n", self.specs_imported)); + output.push_str(&format!(" Types: {}\n", self.types_imported)); + + if !self.schemas.created.is_empty() { + output.push_str("\nCreated Schemas:\n"); + for schema in &self.schemas.created { + output.push_str(&format!(" - {}\n", schema)); + } + } + + output + } +} diff --git a/cli/src/commands/import/output_tests.rs b/cli/src/commands/import/output_tests.rs new file mode 100644 index 0000000..f40f0db --- /dev/null +++ b/cli/src/commands/import/output_tests.rs @@ -0,0 +1,119 @@ +//! Output formatting tests for import command. + +#[cfg(test)] +mod tests { + use crate::output::OutputFormat; + use crate::queries::import::{ImportResult, SchemaResult}; + use rstest::{fixture, rstest}; + + const EMPTY_TABLE_OUTPUT: &str = "\ +Import Summary: + Modules: 0 + Functions: 0 + Calls: 0 + Structs: 0 + Locations: 0 + Specs: 0 + Types: 0 +"; + + const FULL_TABLE_OUTPUT: &str = "\ +Cleared existing project data. + +Import Summary: + Modules: 10 + Functions: 50 + Calls: 100 + Structs: 5 + Locations: 45 + Specs: 25 + Types: 12 + +Created Schemas: + - modules + - functions +"; + + const FULL_TABLE_OUTPUT_NO_CLEAR: &str = "\ +Import Summary: + Modules: 10 + Functions: 50 + Calls: 100 + Structs: 5 + Locations: 45 + Specs: 25 + Types: 12 + +Created Schemas: + - modules + - functions +"; + + + #[fixture] + fn empty_result() -> ImportResult { + ImportResult::default() + } + + #[fixture] + fn full_result() -> ImportResult { + ImportResult { + schemas: SchemaResult { + created: vec!["modules".to_string(), "functions".to_string()], + already_existed: vec!["calls".to_string()], + }, + cleared: true, + modules_imported: 10, + functions_imported: 50, + calls_imported: 100, + structs_imported: 5, + function_locations_imported: 45, + specs_imported: 25, + types_imported: 12, + } + } + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ImportResult, + expected: EMPTY_TABLE_OUTPUT, + } + + crate::output_table_test! { + test_name: test_to_table_with_data, + fixture: full_result, + fixture_type: ImportResult, + expected: FULL_TABLE_OUTPUT, + } + + #[rstest] + fn test_to_table_no_clear(full_result: ImportResult) { + use crate::output::Outputable; + let mut result = full_result; + result.cleared = false; + assert_eq!(result.to_table(), FULL_TABLE_OUTPUT_NO_CLEAR); + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: full_result, + fixture_type: ImportResult, + expected: crate::test_utils::load_output_fixture("import", "full.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: full_result, + fixture_type: ImportResult, + expected: crate::test_utils::load_output_fixture("import", "full.toon"), + format: Toon, + } + + #[rstest] + fn test_format_table_delegates_to_to_table(full_result: ImportResult) { + use crate::output::Outputable; + assert_eq!(full_result.format(OutputFormat::Table), FULL_TABLE_OUTPUT); + } +} diff --git a/cli/src/commands/large_functions/execute.rs b/cli/src/commands/large_functions/execute.rs new file mode 100644 index 0000000..576fcfd --- /dev/null +++ b/cli/src/commands/large_functions/execute.rs @@ -0,0 +1,108 @@ +use std::collections::HashMap; +use std::error::Error; + +use serde::Serialize; + +use super::LargeFunctionsCmd; +use crate::commands::Execute; +use crate::queries::large_functions::find_large_functions; +use crate::types::{ModuleCollectionResult, ModuleGroup}; + +/// A single large function entry +#[derive(Debug, Clone, Serialize)] +pub struct LargeFunctionEntry { + pub name: String, + pub arity: i64, + pub start_line: i64, + pub end_line: i64, + pub lines: i64, + pub file: String, +} + +impl Execute for LargeFunctionsCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let large_functions = find_large_functions( + db, + self.min_lines, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.include_generated, + self.common.limit, + )?; + + let total_items = large_functions.len(); + + // Group by module while preserving sort order (largest functions first) + // Track module order separately to maintain insertion order + let mut module_order: Vec = Vec::new(); + let mut module_map: HashMap)> = HashMap::new(); + + for func in large_functions { + let entry = LargeFunctionEntry { + name: func.name, + arity: func.arity, + start_line: func.start_line, + end_line: func.end_line, + lines: func.lines, + file: func.file.clone(), + }; + + if !module_map.contains_key(&func.module) { + module_order.push(func.module.clone()); + } + + module_map + .entry(func.module) + .or_insert_with(|| (func.file, Vec::new())) + .1 + .push(entry); + } + + let items: Vec> = module_order + .into_iter() + .filter_map(|name| { + module_map.remove(&name).map(|(file, entries)| ModuleGroup { + name, + file, + entries, + function_count: None, + }) + }) + .collect(); + + Ok(ModuleCollectionResult { + module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items, + items, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_large_functions_cmd_structure() { + let cmd = LargeFunctionsCmd { + min_lines: 100, + include_generated: false, + module: Some("MyApp".to_string()), + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 20, + }, + }; + + assert_eq!(cmd.min_lines, 100); + assert!(!cmd.include_generated); + assert_eq!(cmd.module, Some("MyApp".to_string())); + } +} diff --git a/cli/src/commands/large_functions/mod.rs b/cli/src/commands/large_functions/mod.rs new file mode 100644 index 0000000..245fead --- /dev/null +++ b/cli/src/commands/large_functions/mod.rs @@ -0,0 +1,46 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find large functions that may need refactoring +/// +/// Large functions are those with many lines of code (large `end_line - start_line`). +/// These typically indicate functions that should be broken down into smaller pieces. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search large-functions # Find functions with 50+ lines + code_search large-functions MyApp.Web # Filter to MyApp.Web namespace + code_search large-functions --min-lines 100 # Find functions with 100+ lines + code_search large-functions --include-generated # Include macro-generated functions + code_search large-functions -l 20 # Show top 20 largest functions +")] +pub struct LargeFunctionsCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Minimum lines to be considered large + #[arg(long, default_value = "50")] + pub min_lines: i64, + + /// Include macro-generated functions (excluded by default) + #[arg(long)] + pub include_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for LargeFunctionsCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/large_functions/output.rs b/cli/src/commands/large_functions/output.rs new file mode 100644 index 0000000..f133de2 --- /dev/null +++ b/cli/src/commands/large_functions/output.rs @@ -0,0 +1,40 @@ +//! Output formatting for large functions command results. + +use super::execute::LargeFunctionEntry; +use crate::output::TableFormatter; +use crate::types::ModuleCollectionResult; + +impl TableFormatter for ModuleCollectionResult { + type Entry = LargeFunctionEntry; + + fn format_header(&self) -> String { + "Large Functions".to_string() + } + + fn format_empty_message(&self) -> String { + "No large functions found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} large function(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, entry: &LargeFunctionEntry, _module: &str, _file: &str) -> String { + format!( + "{}/{} ({} lines) - {}:{}-{}", + entry.name, entry.arity, entry.lines, entry.file, entry.start_line, entry.end_line + ) + } + + fn blank_before_module(&self) -> bool { + true + } + + fn blank_after_summary(&self) -> bool { + false + } +} diff --git a/cli/src/commands/location/cli_tests.rs b/cli/src/commands/location/cli_tests.rs new file mode 100644 index 0000000..b3b0dfc --- /dev/null +++ b/cli/src/commands/location/cli_tests.rs @@ -0,0 +1,91 @@ +//! CLI parsing tests for location command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "location", + test_name: test_requires_function, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_function_only, + args: ["get_user"], + field: function, + expected: "get_user", + } + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_module, + args: ["get_user", "MyApp.Accounts"], + field: module, + expected: Some("MyApp.Accounts".to_string()), + } + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_arity, + args: ["get_user", "MyApp.Accounts", "--arity", "1"], + field: arity, + expected: Some(1), + } + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_regex, + args: ["get_.*", "MyApp.*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_project, + args: ["get_user", "MyApp.Accounts", "--project", "my_app"], + field: common.project, + expected: "my_app", + } + + crate::cli_option_test! { + command: "location", + variant: Location, + test_name: test_with_limit, + args: ["get_user", "--limit", "10"], + field: common.limit, + expected: 10, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "location", + variant: Location, + required_args: ["get_user"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/location/execute.rs b/cli/src/commands/location/execute.rs new file mode 100644 index 0000000..fd1c6d6 --- /dev/null +++ b/cli/src/commands/location/execute.rs @@ -0,0 +1,131 @@ +use std::collections::BTreeMap; +use std::error::Error; + +use serde::Serialize; + +use super::LocationCmd; +use crate::commands::Execute; +use crate::queries::location::{find_locations, FunctionLocation}; + +/// A single clause (definition) of a function +#[derive(Debug, Clone, Serialize)] +pub struct LocationClause { + pub line: i64, + pub start_line: i64, + pub end_line: i64, + #[serde(skip_serializing_if = "String::is_empty")] + pub pattern: String, + #[serde(skip_serializing_if = "String::is_empty")] + pub guard: String, +} + +/// A function with all its clauses grouped together +#[derive(Debug, Clone, Serialize)] +pub struct LocationFunction { + pub name: String, + pub arity: i64, + pub kind: String, + pub file: String, + pub clauses: Vec, +} + +/// A module containing functions +#[derive(Debug, Clone, Serialize)] +pub struct LocationModule { + pub name: String, + pub functions: Vec, +} + +/// Result of the location command execution +#[derive(Debug, Default, Serialize)] +pub struct LocationResult { + pub module_pattern: String, + pub function_pattern: String, + pub total_clauses: usize, + pub modules: Vec, +} + +impl LocationResult { + /// Build grouped result from flat FunctionLocation list + fn from_locations( + module_pattern: String, + function_pattern: String, + locations: Vec, + ) -> Self { + let total_clauses = locations.len(); + + // Group by module, then by (function_name, arity) + // Use BTreeMap for consistent ordering + let mut module_map: BTreeMap)>> = + BTreeMap::new(); + + for loc in locations { + let func_key = (loc.name.clone(), loc.arity); + let clause = LocationClause { + line: loc.line, + start_line: loc.start_line, + end_line: loc.end_line, + pattern: loc.pattern, + guard: loc.guard, + }; + + module_map + .entry(loc.module.clone()) + .or_default() + .entry(func_key) + .or_insert_with(|| (loc.kind.clone(), loc.file.clone(), Vec::new())) + .2 + .push(clause); + } + + // Convert to final structure + let modules: Vec = module_map + .into_iter() + .map(|(module_name, funcs)| { + let functions: Vec = funcs + .into_iter() + .map(|((name, arity), (kind, file, clauses))| LocationFunction { + name, + arity, + kind, + file, + clauses, + }) + .collect(); + LocationModule { + name: module_name, + functions, + } + }) + .collect(); + + LocationResult { + module_pattern, + function_pattern, + total_clauses, + modules, + } + } +} + +impl Execute for LocationCmd { + type Output = LocationResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let locations = find_locations( + db, + self.module.as_deref(), + &self.function, + self.arity, + &self.common.project, + self.common.regex, + self.common.limit, + )?; + + Ok(LocationResult::from_locations( + self.module.unwrap_or_default(), + self.function, + locations, + )) + } +} diff --git a/cli/src/commands/location/execute_tests.rs b/cli/src/commands/location/execute_tests.rs new file mode 100644 index 0000000..a195c30 --- /dev/null +++ b/cli/src/commands/location/execute_tests.rs @@ -0,0 +1,320 @@ +//! Execute tests for location command. + +#[cfg(test)] +mod tests { + use super::super::LocationCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + crate::execute_test! { + test_name: test_location_exact_match, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp.Accounts".to_string()), + function: "get_user".to_string(), + arity: Some(1), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.modules.len(), 1); + assert_eq!(result.modules[0].functions.len(), 1); + let func = &result.modules[0].functions[0]; + assert_eq!(func.file, "lib/my_app/accounts.ex"); + assert_eq!(func.clauses[0].start_line, 10); + assert_eq!(func.clauses[0].end_line, 15); + }, + } + + // get_user exists in Accounts with arities 1 and 2 + crate::execute_test! { + test_name: test_location_without_module, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + // 2 functions (get_user/1 and get_user/2) in 1 module + assert_eq!(result.total_clauses, 2); + assert_eq!(result.modules.len(), 1); + assert_eq!(result.modules[0].name, "MyApp.Accounts"); + assert_eq!(result.modules[0].functions.len(), 2); + }, + } + + // Functions with "user" in name: get_user/1, get_user/2, list_users = 3 + crate::execute_test! { + test_name: test_location_without_module_multiple_matches, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: ".*user.*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 3); + }, + } + + // get_user has two arities in Accounts + crate::execute_test! { + test_name: test_location_without_arity, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp.Accounts".to_string()), + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 2); + }, + } + + crate::execute_test! { + test_name: test_location_with_regex, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp\\..*".to_string()), + function: ".*user.*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 3); + }, + } + + crate::execute_test! { + test_name: test_location_format, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp.Accounts".to_string()), + function: "get_user".to_string(), + arity: Some(1), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + let func = &result.modules[0].functions[0]; + assert_eq!( + format!("{}:{}:{}", func.file, func.clauses[0].start_line, func.clauses[0].end_line), + "lib/my_app/accounts.ex:10:15" + ); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_location_no_match, + fixture: populated_db, + cmd: LocationCmd { + module: Some("NonExistent".to_string()), + function: "foo".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: modules, + } + + crate::execute_no_match_test! { + test_name: test_location_nonexistent_project, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "nonexistent_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: modules, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_location_with_project_filter, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp.Accounts".to_string()), + function: "get_user".to_string(), + arity: Some(1), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.modules.len(), 1); + assert_eq!(result.modules[0].functions.len(), 1); + }, + } + + // 6 functions with arity 1: get_user/1, validate_email, process, fetch, all, notify + crate::execute_test! { + test_name: test_location_arity_filter_without_module, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: ".*".to_string(), + arity: Some(1), + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + let total_funcs: usize = result.modules.iter().map(|m| m.functions.len()).sum(); + assert_eq!(total_funcs, 6); + // All functions should have arity 1 + for module in &result.modules { + for func in &module.functions { + assert_eq!(func.arity, 1); + } + } + }, + } + + crate::execute_test! { + test_name: test_location_project_filter_without_module, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: "get_user".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 2); + }, + } + + // Accounts has get_user/1, get_user/2, list_users matching ".*user.*" = 3 + crate::execute_test! { + test_name: test_location_function_regex_with_exact_module, + fixture: populated_db, + cmd: LocationCmd { + module: Some("MyApp.Accounts".to_string()), + function: ".*user.*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 3); + }, + } + + crate::execute_test! { + test_name: test_location_arity_zero, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: "list_users".to_string(), + arity: Some(0), + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_clauses, 1); + assert_eq!(result.modules[0].functions[0].arity, 0); + }, + } + + crate::execute_test! { + test_name: test_location_with_limit, + fixture: populated_db, + cmd: LocationCmd { + module: None, + function: ".*user.*".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 1, + }, + }, + assertions: |result| { + // Limit applies to raw results before grouping + assert_eq!(result.total_clauses, 1); + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: LocationCmd, + cmd: LocationCmd { + module: Some("MyApp".to_string()), + function: "foo".to_string(), + arity: None, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/location/mod.rs b/cli/src/commands/location/mod.rs new file mode 100644 index 0000000..b4b016e --- /dev/null +++ b/cli/src/commands/location/mod.rs @@ -0,0 +1,44 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find where a function is defined (file:line_start:line_end) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search location get_user # Find all get_user functions + code_search location get_user MyApp # In specific module + code_search location get_user -a 1 # With specific arity + code_search location -r 'get_.*' # Regex pattern matching +")] +pub struct LocationCmd { + /// Function name (exact match or pattern with --regex) + pub function: String, + + /// Module name (exact match or pattern with --regex). If not specified, searches all modules. + pub module: Option, + + /// Function arity (optional, matches all arities if not specified) + #[arg(short, long)] + pub arity: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for LocationCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/location/output.rs b/cli/src/commands/location/output.rs new file mode 100644 index 0000000..7a6a80f --- /dev/null +++ b/cli/src/commands/location/output.rs @@ -0,0 +1,54 @@ +//! Output formatting for location command results. + +use crate::output::Outputable; +use super::execute::LocationResult; + +impl Outputable for LocationResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + lines.push(format!("Location: {}.{}", self.module_pattern, self.function_pattern)); + lines.push(String::new()); + + if !self.modules.is_empty() { + let func_count: usize = self.modules.iter().map(|m| m.functions.len()).sum(); + lines.push(format!( + "Found {} clause(s) in {} function(s) across {} module(s):", + self.total_clauses, + func_count, + self.modules.len() + )); + lines.push(String::new()); + + for module in &self.modules { + lines.push(format!("{}:", module.name)); + for func in &module.functions { + lines.push(format!( + " {}/{} [{}] ({})", + func.name, func.arity, func.kind, func.file + )); + for clause in &func.clauses { + let pattern_str = if clause.pattern.is_empty() { + String::new() + } else { + format!(" ({})", clause.pattern) + }; + let guard_str = if clause.guard.is_empty() { + String::new() + } else { + format!(" when {}", clause.guard) + }; + lines.push(format!( + " L{}:{}{}{}", + clause.start_line, clause.end_line, pattern_str, guard_str + )); + } + } + } + } else { + lines.push("No locations found.".to_string()); + } + + lines.join("\n") + } +} diff --git a/cli/src/commands/location/output_tests.rs b/cli/src/commands/location/output_tests.rs new file mode 100644 index 0000000..2c7f752 --- /dev/null +++ b/cli/src/commands/location/output_tests.rs @@ -0,0 +1,169 @@ +//! Output formatting tests for location command. + +#[cfg(test)] +mod tests { + use super::super::execute::{LocationClause, LocationFunction, LocationModule, LocationResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Location: MyApp.foo + +No locations found."; + + const SINGLE_TABLE: &str = "\ +Location: MyApp.Accounts.get_user + +Found 1 clause(s) in 1 function(s) across 1 module(s): + +MyApp.Accounts: + get_user/1 [def] (lib/my_app/accounts.ex) + L10:15"; + + const MULTIPLE_TABLE: &str = "\ +Location: MyApp.*.user + +Found 2 clause(s) in 2 function(s) across 2 module(s): + +MyApp.Accounts: + get_user/1 [def] (lib/my_app/accounts.ex) + L10:15 +MyApp.Users: + create_user/1 [def] (lib/my_app/users.ex) + L5:12"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> LocationResult { + LocationResult { + module_pattern: "MyApp".to_string(), + function_pattern: "foo".to_string(), + total_clauses: 0, + modules: vec![], + } + } + + #[fixture] + fn single_result() -> LocationResult { + LocationResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: "get_user".to_string(), + total_clauses: 1, + modules: vec![LocationModule { + name: "MyApp.Accounts".to_string(), + functions: vec![LocationFunction { + name: "get_user".to_string(), + arity: 1, + kind: "def".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + clauses: vec![LocationClause { + line: 10, + start_line: 10, + end_line: 15, + pattern: String::new(), + guard: String::new(), + }], + }], + }], + } + } + + #[fixture] + fn multiple_result() -> LocationResult { + LocationResult { + module_pattern: "MyApp.*".to_string(), + function_pattern: "user".to_string(), + total_clauses: 2, + modules: vec![ + LocationModule { + name: "MyApp.Accounts".to_string(), + functions: vec![LocationFunction { + name: "get_user".to_string(), + arity: 1, + kind: "def".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + clauses: vec![LocationClause { + line: 10, + start_line: 10, + end_line: 15, + pattern: String::new(), + guard: String::new(), + }], + }], + }, + LocationModule { + name: "MyApp.Users".to_string(), + functions: vec![LocationFunction { + name: "create_user".to_string(), + arity: 1, + kind: "def".to_string(), + file: "lib/my_app/users.ex".to_string(), + clauses: vec![LocationClause { + line: 5, + start_line: 5, + end_line: 12, + pattern: String::new(), + guard: String::new(), + }], + }], + }, + ], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: LocationResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: LocationResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_multiple, + fixture: multiple_result, + fixture_type: LocationResult, + expected: MULTIPLE_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: LocationResult, + expected: crate::test_utils::load_output_fixture("location", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: LocationResult, + expected: crate::test_utils::load_output_fixture("location", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: LocationResult, + expected: crate::test_utils::load_output_fixture("location", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/many_clauses/execute.rs b/cli/src/commands/many_clauses/execute.rs new file mode 100644 index 0000000..32d8757 --- /dev/null +++ b/cli/src/commands/many_clauses/execute.rs @@ -0,0 +1,107 @@ +use std::collections::HashMap; +use std::error::Error; + +use serde::Serialize; + +use super::ManyClausesCmd; +use crate::commands::Execute; +use crate::queries::many_clauses::find_many_clauses; +use crate::types::{ModuleCollectionResult, ModuleGroup}; + +/// A single function with many clauses entry +#[derive(Debug, Clone, Serialize)] +pub struct ManyClausesEntry { + pub name: String, + pub arity: i64, + pub clauses: i64, + pub first_line: i64, + pub last_line: i64, + pub file: String, +} + +impl Execute for ManyClausesCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let many_clauses = find_many_clauses( + db, + self.min_clauses, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.include_generated, + self.common.limit, + )?; + + let total_items = many_clauses.len(); + + // Group by module while preserving sort order (most clauses first) + let mut module_order: Vec = Vec::new(); + let mut module_map: HashMap)> = HashMap::new(); + + for func in many_clauses { + let entry = ManyClausesEntry { + name: func.name, + arity: func.arity, + clauses: func.clauses, + first_line: func.first_line, + last_line: func.last_line, + file: func.file.clone(), + }; + + if !module_map.contains_key(&func.module) { + module_order.push(func.module.clone()); + } + + module_map + .entry(func.module) + .or_insert_with(|| (func.file, Vec::new())) + .1 + .push(entry); + } + + let items: Vec> = module_order + .into_iter() + .filter_map(|name| { + module_map.remove(&name).map(|(file, entries)| ModuleGroup { + name, + file, + entries, + function_count: None, + }) + }) + .collect(); + + Ok(ModuleCollectionResult { + module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items, + items, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_many_clauses_cmd_structure() { + let cmd = ManyClausesCmd { + min_clauses: 10, + include_generated: false, + module: Some("MyApp".to_string()), + common: crate::commands::CommonArgs { + project: "default".to_string(), + regex: false, + limit: 20, + }, + }; + + assert_eq!(cmd.min_clauses, 10); + assert!(!cmd.include_generated); + assert_eq!(cmd.module, Some("MyApp".to_string())); + } +} diff --git a/cli/src/commands/many_clauses/mod.rs b/cli/src/commands/many_clauses/mod.rs new file mode 100644 index 0000000..3195bc2 --- /dev/null +++ b/cli/src/commands/many_clauses/mod.rs @@ -0,0 +1,47 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions with many pattern-matched heads +/// +/// Functions with many clauses are those with multiple pattern-matched definitions, +/// indicating high branching complexity. These typically indicate functions that +/// should be broken down or simplified. +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search many-clauses # Find functions with 5+ clauses + code_search many-clauses MyApp.Web # Filter to MyApp.Web namespace + code_search many-clauses --min-clauses 10 # Find functions with 10+ clauses + code_search many-clauses --include-generated # Include macro-generated functions + code_search many-clauses -l 20 # Show top 20 functions with most clauses +")] +pub struct ManyClausesCmd { + /// Module filter pattern (substring match by default, regex with --regex) + pub module: Option, + + /// Minimum clauses to be considered + #[arg(long, default_value = "5")] + pub min_clauses: i64, + + /// Include macro-generated functions (excluded by default) + #[arg(long)] + pub include_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for ManyClausesCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/many_clauses/output.rs b/cli/src/commands/many_clauses/output.rs new file mode 100644 index 0000000..32b9a33 --- /dev/null +++ b/cli/src/commands/many_clauses/output.rs @@ -0,0 +1,40 @@ +//! Output formatting for many clauses command results. + +use super::execute::ManyClausesEntry; +use crate::output::TableFormatter; +use crate::types::ModuleCollectionResult; + +impl TableFormatter for ModuleCollectionResult { + type Entry = ManyClausesEntry; + + fn format_header(&self) -> String { + "Functions with Many Clauses".to_string() + } + + fn format_empty_message(&self) -> String { + "No functions with many clauses found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} function(s) with many clauses in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, entry: &ManyClausesEntry, _module: &str, _file: &str) -> String { + format!( + "{}/{} ({} clauses) - {}:{}-{}", + entry.name, entry.arity, entry.clauses, entry.file, entry.first_line, entry.last_line + ) + } + + fn blank_before_module(&self) -> bool { + true + } + + fn blank_after_summary(&self) -> bool { + false + } +} diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs new file mode 100644 index 0000000..eac19b7 --- /dev/null +++ b/cli/src/commands/mod.rs @@ -0,0 +1,209 @@ +//! Command definitions and implementations. +//! +//! Each command is defined in its own module with: +//! - The command struct with clap attributes for CLI parsing +//! - Common arguments shared via [`CommonArgs`] + +use clap::Args; + +/// Common arguments shared across most commands. +/// +/// Use `#[command(flatten)]` to include these in a command struct: +/// ```ignore +/// pub struct MyCmd { +/// pub module: String, +/// #[command(flatten)] +/// pub common: CommonArgs, +/// } +/// ``` +#[derive(Args, Debug, Clone)] +pub struct CommonArgs { + /// Project to search in + #[arg(long, default_value = "default")] + pub project: String, + + /// Treat patterns as regular expressions + #[arg(short, long, default_value_t = false)] + pub regex: bool, + + /// Maximum number of results to return (1-1000) + #[arg(short, long, default_value_t = 100, value_parser = clap::value_parser!(u32).range(1..=1000))] + pub limit: u32, +} + +mod accepts; +mod boundaries; +mod browse_module; +mod calls_from; +mod calls_to; +mod clusters; +mod complexity; +mod cycles; +mod depended_by; +mod depends_on; +mod describe; +mod duplicates; +mod function; +mod god_modules; +mod hotspots; +pub mod import; +mod large_functions; +mod location; +mod many_clauses; +mod path; +mod returns; +mod reverse_trace; +mod search; +pub mod setup; +mod struct_usage; +mod trace; +mod unused; + +pub use accepts::AcceptsCmd; +pub use boundaries::BoundariesCmd; +pub use browse_module::BrowseModuleCmd; +pub use calls_from::CallsFromCmd; +pub use calls_to::CallsToCmd; +pub use clusters::ClustersCmd; +pub use complexity::ComplexityCmd; +pub use cycles::CyclesCmd; +pub use depended_by::DependedByCmd; +pub use depends_on::DependsOnCmd; +pub use describe::DescribeCmd; +pub use duplicates::DuplicatesCmd; +pub use function::FunctionCmd; +pub use god_modules::GodModulesCmd; +pub use hotspots::HotspotsCmd; +pub use import::ImportCmd; +pub use large_functions::LargeFunctionsCmd; +pub use location::LocationCmd; +pub use many_clauses::ManyClausesCmd; +pub use path::PathCmd; +pub use returns::ReturnsCmd; +pub use reverse_trace::ReverseTraceCmd; +pub use search::SearchCmd; +pub use setup::SetupCmd; +pub use struct_usage::StructUsageCmd; +pub use trace::TraceCmd; +pub use unused::UnusedCmd; + +use clap::Subcommand; +use enum_dispatch::enum_dispatch; +use std::error::Error; + +use cozo::DbInstance; + +use crate::output::{OutputFormat, Outputable}; + +/// Trait for executing commands with command-specific result types. +pub trait Execute { + type Output: Outputable; + + fn execute(self, db: &DbInstance) -> Result>; +} + +/// Trait for commands that can be executed and formatted. +/// Auto-implemented for all Command variants via enum_dispatch. +#[enum_dispatch] +pub trait CommandRunner { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result>; +} + +#[derive(Subcommand, Debug)] +#[enum_dispatch(CommandRunner)] +pub enum Command { + /// Create database schema without importing data + Setup(SetupCmd), + + /// Import a call graph JSON file into the database + Import(ImportCmd), + + /// Browse all definitions in a module or file + BrowseModule(BrowseModuleCmd), + + /// Search for modules or functions by name pattern + Search(SearchCmd), + + /// Find where a function is defined (file:line_start:line_end) + Location(LocationCmd), + + /// Show what a module/function calls (outgoing edges) + CallsFrom(CallsFromCmd), + + /// Show what calls a module/function (incoming edges) + CallsTo(CallsToCmd), + + /// Analyze module connectivity using namespace-based clustering + Clusters(ClustersCmd), + + /// Display complexity metrics for functions + Complexity(ComplexityCmd), + + /// Detect circular dependencies between modules + Cycles(CyclesCmd), + + /// Display detailed documentation about available commands + Describe(DescribeCmd), + + /// Show function signature (args, return type) + Function(FunctionCmd), + + /// Trace call chains from a starting function (forward traversal) + Trace(TraceCmd), + + /// Trace call chains backwards - who calls the callers of a target + ReverseTrace(ReverseTraceCmd), + + /// Find a call path between two functions + Path(PathCmd), + + /// Find functions accepting a specific type pattern + Accepts(AcceptsCmd), + + /// Find functions returning a specific type pattern + Returns(ReturnsCmd), + + /// Find functions that accept or return a specific type pattern + StructUsage(StructUsageCmd), + + /// Show what modules a given module depends on (outgoing module dependencies) + DependsOn(DependsOnCmd), + + /// Show what modules depend on a given module (incoming module dependencies) + DependedBy(DependedByCmd), + + /// Find functions that are never called + Unused(UnusedCmd), + + /// Find functions with identical or near-identical implementations + Duplicates(DuplicatesCmd), + + /// Find functions with the most incoming/outgoing calls + Hotspots(HotspotsCmd), + + /// Find boundary modules - modules with high fan-in but low fan-out + Boundaries(BoundariesCmd), + + /// Find god modules - modules with high function count and high connectivity + GodModules(GodModulesCmd), + + /// Find large functions that may need refactoring + LargeFunctions(LargeFunctionsCmd), + + /// Find functions with many pattern-matched heads + ManyClauses(ManyClausesCmd), + + /// Catch-all for unknown commands + #[command(external_subcommand)] + Unknown(Vec), +} + +// CommandRunner implementations are provided by each command's module. +// The enum_dispatch macro automatically generates dispatch logic for the Command enum. + +// Special handling for Unknown variant - not a real command +impl CommandRunner for Vec { + fn run(self, _db: &DbInstance, _format: OutputFormat) -> Result> { + Err(format!("Unknown command: {}", self.first().unwrap_or(&String::new())).into()) + } +} diff --git a/cli/src/commands/path/cli_tests.rs b/cli/src/commands/path/cli_tests.rs new file mode 100644 index 0000000..2ae388b --- /dev/null +++ b/cli/src/commands/path/cli_tests.rs @@ -0,0 +1,187 @@ +//! CLI parsing tests for path command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + // Path command has many required args, so we test them as edge cases below + + crate::cli_option_test! { + command: "path", + variant: Path, + test_name: test_with_limit, + args: [ + "--from-module", "MyApp", + "--from-function", "foo", + "--to-module", "MyApp", + "--to-function", "bar", + "--limit", "5" + ], + field: limit, + expected: 5, + } + + crate::cli_option_test! { + command: "path", + variant: Path, + test_name: test_with_depth, + args: [ + "--from-module", "MyApp", + "--from-function", "foo", + "--to-module", "MyApp", + "--to-function", "bar", + "--depth", "15" + ], + field: depth, + expected: 15, + } + + crate::cli_option_test! { + command: "path", + variant: Path, + test_name: test_with_arities, + args: [ + "--from-module", "MyApp.Controller", + "--from-function", "index", + "--from-arity", "2", + "--to-module", "MyApp.Repo", + "--to-function", "get", + "--to-arity", "2" + ], + field: from_arity, + expected: Some(2), + } + + // ========================================================================= + // Edge case tests (multiple required args, depth validation) + // ========================================================================= + + #[rstest] + fn test_requires_all_args() { + let result = Args::try_parse_from(["code_search", "path"]); + assert!(result.is_err()); + } + + #[rstest] + fn test_requires_to_args() { + let result = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp.Controller", + "--from-function", + "index", + ]); + assert!(result.is_err()); + } + + #[rstest] + fn test_with_all_required_args() { + let args = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp.Controller", + "--from-function", + "index", + "--to-module", + "MyApp.Repo", + "--to-function", + "get", + ]) + .unwrap(); + match args.command { + crate::commands::Command::Path(cmd) => { + assert_eq!(cmd.from_module, "MyApp.Controller"); + assert_eq!(cmd.from_function, "index"); + assert_eq!(cmd.to_module, "MyApp.Repo"); + assert_eq!(cmd.to_function, "get"); + assert_eq!(cmd.depth, 10); // default + assert_eq!(cmd.limit, 100); // default + } + _ => panic!("Expected Path command"), + } + } + + #[rstest] + fn test_depth_zero_rejected() { + let result = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp", + "--from-function", + "foo", + "--to-module", + "MyApp", + "--to-function", + "bar", + "--depth", + "0", + ]); + assert!(result.is_err()); + } + + #[rstest] + fn test_depth_exceeds_max_rejected() { + let result = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp", + "--from-function", + "foo", + "--to-module", + "MyApp", + "--to-function", + "bar", + "--depth", + "21", + ]); + assert!(result.is_err()); + } + + #[rstest] + fn test_limit_zero_rejected() { + let result = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp", + "--from-function", + "foo", + "--to-module", + "MyApp", + "--to-function", + "bar", + "--limit", + "0", + ]); + assert!(result.is_err()); + } + + #[rstest] + fn test_limit_exceeds_max_rejected() { + let result = Args::try_parse_from([ + "code_search", + "path", + "--from-module", + "MyApp", + "--from-function", + "foo", + "--to-module", + "MyApp", + "--to-function", + "bar", + "--limit", + "1001", + ]); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/path/execute.rs b/cli/src/commands/path/execute.rs new file mode 100644 index 0000000..2dee335 --- /dev/null +++ b/cli/src/commands/path/execute.rs @@ -0,0 +1,48 @@ +use std::error::Error; + +use serde::Serialize; + +use super::PathCmd; +use crate::commands::Execute; +use crate::queries::path::{find_paths, CallPath}; + +/// Result of the path command execution +#[derive(Debug, Default, Serialize)] +pub struct PathResult { + pub from_module: String, + pub from_function: String, + pub to_module: String, + pub to_function: String, + pub max_depth: u32, + pub paths: Vec, +} + +impl Execute for PathCmd { + type Output = PathResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let mut result = PathResult { + from_module: self.from_module.clone(), + from_function: self.from_function.clone(), + to_module: self.to_module.clone(), + to_function: self.to_function.clone(), + max_depth: self.depth, + ..Default::default() + }; + + result.paths = find_paths( + db, + &self.from_module, + &self.from_function, + self.from_arity, + &self.to_module, + &self.to_function, + self.to_arity, + &self.project, + self.depth, + self.limit, + )?; + + Ok(result) + } +} \ No newline at end of file diff --git a/cli/src/commands/path/execute_tests.rs b/cli/src/commands/path/execute_tests.rs new file mode 100644 index 0000000..86ffbe1 --- /dev/null +++ b/cli/src/commands/path/execute_tests.rs @@ -0,0 +1,209 @@ +//! Execute tests for path command. + +#[cfg(test)] +mod tests { + use super::super::PathCmd; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // Controller.index -> Accounts.list_users (direct call) + crate::execute_test! { + test_name: test_path_direct_call, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + from_arity: None, + to_module: "MyApp.Accounts".to_string(), + to_function: "list_users".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + assertions: |result| { + assert_eq!(result.paths.len(), 1); + assert_eq!(result.paths[0].steps.len(), 1); + assert_eq!(result.paths[0].steps[0].caller_module, "MyApp.Controller"); + assert_eq!(result.paths[0].steps[0].callee_module, "MyApp.Accounts"); + }, + } + + // Controller.index -> Accounts.list_users -> Repo.all (2 hops) + crate::execute_test! { + test_name: test_path_two_hops, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + from_arity: None, + to_module: "MyApp.Repo".to_string(), + to_function: "all".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + assertions: |result| { + assert_eq!(result.paths.len(), 1); + assert_eq!(result.paths[0].steps.len(), 2); + }, + } + + // Controller.show -> Accounts.get_user -> Repo.get (2 hops) + // Both get_user/1 and get_user/2 call Repo.get, so 2 paths found + crate::execute_test! { + test_name: test_path_via_accounts, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "show".to_string(), + from_arity: None, + to_module: "MyApp.Repo".to_string(), + to_function: "get".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + assertions: |result| { + assert_eq!(result.paths.len(), 2); + assert!(result.paths.iter().all(|p| p.steps.len() == 2)); + }, + } + + // ========================================================================= + // Arity filtering tests + // ========================================================================= + + // Controller.show/2 -> Accounts.get_user/1 -> Repo.get (with from_arity) + crate::execute_test! { + test_name: test_path_with_from_arity, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "show".to_string(), + from_arity: Some(2), + to_module: "MyApp.Repo".to_string(), + to_function: "get".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + assertions: |result| { + // Should find paths via get_user/1 and get_user/2 + assert!(!result.paths.is_empty()); + // First step caller should be show/2 + assert!(result.paths[0].steps[0].caller_function.starts_with("show")); + }, + } + + // Controller.index/2 -> Accounts.list_users/0 (with from_arity exact match) + crate::execute_test! { + test_name: test_path_with_from_arity_exact, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + from_arity: Some(2), + to_module: "MyApp.Accounts".to_string(), + to_function: "list_users".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + assertions: |result| { + assert_eq!(result.paths.len(), 1); + // caller_function is just the name (no arity suffix in calls table) + assert_eq!(result.paths[0].steps[0].caller_function, "index"); + }, + } + + // Wrong arity should find no paths + crate::execute_no_match_test! { + test_name: test_path_with_wrong_from_arity, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + from_arity: Some(99), // Wrong arity - index is /2 + to_module: "MyApp.Accounts".to_string(), + to_function: "list_users".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + empty_field: paths, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + // No path from Repo back to Controller (acyclic) + crate::execute_no_match_test! { + test_name: test_path_no_path_exists, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Repo".to_string(), + from_function: "get".to_string(), + from_arity: None, + to_module: "MyApp.Controller".to_string(), + to_function: "index".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + empty_field: paths, + } + + // Depth 1 can't reach Repo.all from Controller.index (needs 2 hops) + crate::execute_no_match_test! { + test_name: test_path_depth_limit, + fixture: populated_db, + cmd: PathCmd { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + from_arity: None, + to_module: "MyApp.Repo".to_string(), + to_function: "all".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 1, + limit: 10, + }, + empty_field: paths, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: PathCmd, + cmd: PathCmd { + from_module: "MyApp".to_string(), + from_function: "foo".to_string(), + from_arity: None, + to_module: "MyApp".to_string(), + to_function: "bar".to_string(), + to_arity: None, + project: "test_project".to_string(), + depth: 10, + limit: 10, + }, + } +} diff --git a/cli/src/commands/path/mod.rs b/cli/src/commands/path/mod.rs new file mode 100644 index 0000000..75d4f25 --- /dev/null +++ b/cli/src/commands/path/mod.rs @@ -0,0 +1,66 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find a call path between two functions +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search path --from-module MyApp.Web --from-function index \\ + --to-module MyApp.Repo --to-function get + code_search path --from-module MyApp.API --from-function create \\ + --to-module Ecto.Repo --to-function insert --depth 15")] +pub struct PathCmd { + /// Source module name + #[arg(long)] + pub from_module: String, + + /// Source function name + #[arg(long)] + pub from_function: String, + + /// Source function arity (optional) + #[arg(long)] + pub from_arity: Option, + + /// Target module name + #[arg(long)] + pub to_module: String, + + /// Target function name + #[arg(long)] + pub to_function: String, + + /// Target function arity (optional) + #[arg(long)] + pub to_arity: Option, + + /// Project to search in + #[arg(long, default_value = "default")] + pub project: String, + + /// Maximum depth to search (1-20) + #[arg(long, default_value_t = 10, value_parser = clap::value_parser!(u32).range(1..=20))] + pub depth: u32, + + /// Maximum number of paths to return (1-1000) + #[arg(short, long, default_value_t = 100, value_parser = clap::value_parser!(u32).range(1..=1000))] + pub limit: u32, +} + +impl CommandRunner for PathCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/path/output.rs b/cli/src/commands/path/output.rs new file mode 100644 index 0000000..06297a0 --- /dev/null +++ b/cli/src/commands/path/output.rs @@ -0,0 +1,39 @@ +//! Output formatting for path command results. + +use crate::output::Outputable; +use super::execute::PathResult; + +impl Outputable for PathResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + let header = format!( + "Path from: {}.{} to: {}.{}", + self.from_module, self.from_function, self.to_module, self.to_function + ); + lines.push(header); + lines.push(format!("Max depth: {}", self.max_depth)); + lines.push(String::new()); + + if !self.paths.is_empty() { + lines.push(format!("Found {} path(s):", self.paths.len())); + for (i, path) in self.paths.iter().enumerate() { + lines.push(String::new()); + lines.push(format!("Path {}:", i + 1)); + for step in &path.steps { + let indent = " ".repeat(step.depth as usize); + let caller = format!("{}.{}", step.caller_module, step.caller_function); + let callee = format!("{}.{}/{}", step.callee_module, step.callee_function, step.callee_arity); + lines.push(format!( + "{}[{}] {} ({}:{}) -> {}", + indent, step.depth, caller, step.file, step.line, callee + )); + } + } + } else { + lines.push("No path found.".to_string()); + } + + lines.join("\n") + } +} diff --git a/cli/src/commands/path/output_tests.rs b/cli/src/commands/path/output_tests.rs new file mode 100644 index 0000000..1fe1805 --- /dev/null +++ b/cli/src/commands/path/output_tests.rs @@ -0,0 +1,122 @@ +//! Output formatting tests for path command. + +#[cfg(test)] +mod tests { + use super::super::execute::PathResult; + use crate::queries::path::{CallPath, PathStep}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Path from: MyApp.Controller.index to: MyApp.Repo.get +Max depth: 10 + +No path found."; + + const SINGLE_PATH_TABLE: &str = "\ +Path from: MyApp.Controller.index to: MyApp.Repo.get +Max depth: 10 + +Found 1 path(s): + +Path 1: + [1] MyApp.Controller.index (lib/controller.ex:7) -> MyApp.Service.fetch/1 + [2] MyApp.Service.fetch (lib/service.ex:15) -> MyApp.Repo.get/2"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> PathResult { + PathResult { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + to_module: "MyApp.Repo".to_string(), + to_function: "get".to_string(), + max_depth: 10, + paths: vec![], + } + } + + #[fixture] + fn single_path_result() -> PathResult { + PathResult { + from_module: "MyApp.Controller".to_string(), + from_function: "index".to_string(), + to_module: "MyApp.Repo".to_string(), + to_function: "get".to_string(), + max_depth: 10, + paths: vec![CallPath { + steps: vec![ + PathStep { + depth: 1, + caller_module: "MyApp.Controller".to_string(), + caller_function: "index".to_string(), + callee_module: "MyApp.Service".to_string(), + callee_function: "fetch".to_string(), + callee_arity: 1, + file: "lib/controller.ex".to_string(), + line: 7, + }, + PathStep { + depth: 2, + caller_module: "MyApp.Service".to_string(), + caller_function: "fetch".to_string(), + callee_module: "MyApp.Repo".to_string(), + callee_function: "get".to_string(), + callee_arity: 2, + file: "lib/service.ex".to_string(), + line: 15, + }, + ], + }], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: PathResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single_path, + fixture: single_path_result, + fixture_type: PathResult, + expected: SINGLE_PATH_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_path_result, + fixture_type: PathResult, + expected: crate::test_utils::load_output_fixture("path", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_path_result, + fixture_type: PathResult, + expected: crate::test_utils::load_output_fixture("path", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: PathResult, + expected: crate::test_utils::load_output_fixture("path", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/returns/execute.rs b/cli/src/commands/returns/execute.rs new file mode 100644 index 0000000..20eeeac --- /dev/null +++ b/cli/src/commands/returns/execute.rs @@ -0,0 +1,67 @@ +use std::error::Error; + +use serde::Serialize; + +use super::ReturnsCmd; +use crate::commands::Execute; +use crate::queries::returns::{find_returns, ReturnEntry}; +use crate::types::ModuleGroupResult; + +/// A function's return type information +#[derive(Debug, Clone, Serialize)] +pub struct ReturnInfo { + pub name: String, + pub arity: i64, + pub return_type: String, + pub line: i64, +} + +impl ModuleGroupResult { + /// Build grouped result from flat ReturnEntry list + fn from_entries( + pattern: String, + module_filter: Option, + entries: Vec, + ) -> Self { + let total_items = entries.len(); + + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let return_info = ReturnInfo { + name: entry.name, + arity: entry.arity, + return_type: entry.return_string, + line: entry.line, + }; + (entry.module, return_info) + }); + + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, + } + } +} + +impl Execute for ReturnsCmd { + type Output = ModuleGroupResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let entries = find_returns( + db, + &self.pattern, + &self.common.project, + self.common.regex, + self.module.as_deref(), + self.common.limit, + )?; + + Ok(>::from_entries( + self.pattern, + self.module, + entries, + )) + } +} diff --git a/cli/src/commands/returns/mod.rs b/cli/src/commands/returns/mod.rs new file mode 100644 index 0000000..98d7674 --- /dev/null +++ b/cli/src/commands/returns/mod.rs @@ -0,0 +1,37 @@ +mod execute; +mod output; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions returning a specific type pattern +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search returns \"User.t\" # Find functions returning User.t + code_search returns \"nil\" # Find functions returning nil + code_search returns \"{:error\" MyApp # Filter to module MyApp + code_search returns -r \"list\\(.*\\)\" # Regex pattern matching +")] +pub struct ReturnsCmd { + /// Type pattern to search for in return types + pub pattern: String, + + /// Module filter pattern + pub module: Option, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for ReturnsCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/returns/output.rs b/cli/src/commands/returns/output.rs new file mode 100644 index 0000000..f4c904d --- /dev/null +++ b/cli/src/commands/returns/output.rs @@ -0,0 +1,30 @@ +//! Output formatting for returns command results. + +use crate::output::TableFormatter; +use crate::types::ModuleGroupResult; +use super::execute::ReturnInfo; + +impl TableFormatter for ModuleGroupResult { + type Entry = ReturnInfo; + + fn format_header(&self) -> String { + let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + format!("Functions returning \"{}\"", pattern) + } + + fn format_empty_message(&self) -> String { + "No functions found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} function(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, return_info: &ReturnInfo, _module: &str, _file: &str) -> String { + format!("{}/{} → {}", return_info.name, return_info.arity, return_info.return_type) + } +} diff --git a/cli/src/commands/reverse_trace/cli_tests.rs b/cli/src/commands/reverse_trace/cli_tests.rs new file mode 100644 index 0000000..c14fc9c --- /dev/null +++ b/cli/src/commands/reverse_trace/cli_tests.rs @@ -0,0 +1,115 @@ +//! CLI parsing tests for reverse-trace command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "reverse-trace", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_required_arg_test! { + command: "reverse-trace", + test_name: test_requires_function, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "reverse-trace", + variant: ReverseTrace, + test_name: test_with_module_and_function, + args: ["MyApp.Repo", "get"], + field: module, + expected: "MyApp.Repo", + } + + crate::cli_option_test! { + command: "reverse-trace", + variant: ReverseTrace, + test_name: test_function_name, + args: ["MyApp.Repo", "get"], + field: function, + expected: "get", + } + + crate::cli_option_test! { + command: "reverse-trace", + variant: ReverseTrace, + test_name: test_with_depth, + args: ["MyApp", "foo", "--depth", "10"], + field: depth, + expected: 10, + } + + crate::cli_option_test! { + command: "reverse-trace", + variant: ReverseTrace, + test_name: test_with_limit, + args: ["MyApp", "foo", "--limit", "50"], + field: common.limit, + expected: 50, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "reverse-trace", + variant: ReverseTrace, + required_args: ["MyApp", "foo"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Edge case tests (depth validation - different from standard limit) + // ========================================================================= + + #[rstest] + fn test_depth_default() { + let args = Args::try_parse_from(["code_search", "reverse-trace", "MyApp.Repo", "get"]) + .unwrap(); + match args.command { + crate::commands::Command::ReverseTrace(cmd) => { + assert_eq!(cmd.depth, 5); + } + _ => panic!("Expected ReverseTrace command"), + } + } + + #[rstest] + fn test_depth_zero_rejected() { + let result = + Args::try_parse_from(["code_search", "reverse-trace", "MyApp", "foo", "--depth", "0"]); + assert!(result.is_err()); + } + + #[rstest] + fn test_depth_exceeds_max_rejected() { + let result = Args::try_parse_from([ + "code_search", + "reverse-trace", + "MyApp", + "foo", + "--depth", + "21", + ]); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/reverse_trace/execute.rs b/cli/src/commands/reverse_trace/execute.rs new file mode 100644 index 0000000..ecb9518 --- /dev/null +++ b/cli/src/commands/reverse_trace/execute.rs @@ -0,0 +1,157 @@ +use std::collections::HashMap; +use std::error::Error; + +use super::ReverseTraceCmd; +use crate::commands::Execute; +use crate::queries::reverse_trace::{reverse_trace_calls, ReverseTraceStep}; +use crate::types::{TraceDirection, TraceEntry, TraceResult}; + +impl TraceResult { + /// Build a flattened reverse-trace from ReverseTraceStep objects + pub fn from_steps( + target_module: String, + target_function: String, + max_depth: u32, + steps: Vec, + ) -> Self { + let mut entries = Vec::new(); + let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); + + if steps.is_empty() { + return Self::empty(target_module, target_function, max_depth, TraceDirection::Backward); + } + + // Group steps by depth + let mut by_depth: HashMap> = HashMap::new(); + for step in &steps { + by_depth.entry(step.depth).or_default().push(step); + } + + // Process depth 1 (direct callers of target function) + if let Some(depth1_steps) = by_depth.get(&1) { + let mut filter = crate::dedup::DeduplicationFilter::new(); + + for step in depth1_steps { + let caller_key = ( + step.caller_module.clone(), + step.caller_function.clone(), + step.caller_arity, + 1i64, + ); + + // Add caller as root entry if not already added + if filter.should_process(caller_key.clone()) { + let entry_idx = entries.len(); + entries.push(TraceEntry { + module: step.caller_module.clone(), + function: step.caller_function.clone(), + arity: step.caller_arity, + kind: step.caller_kind.clone(), + start_line: step.caller_start_line, + end_line: step.caller_end_line, + file: step.file.clone(), + depth: 1, + line: step.line, + parent_index: None, + }); + entry_index_map.insert(caller_key, entry_idx); + } + } + } + + // Process deeper levels (additional callers) + for depth in 2..=max_depth as i64 { + if let Some(depth_steps) = by_depth.get(&depth) { + let mut filter = crate::dedup::DeduplicationFilter::new(); + + for step in depth_steps { + let caller_key = ( + step.caller_module.clone(), + step.caller_function.clone(), + step.caller_arity, + depth, + ); + + // Find parent index (the callee at previous depth, which is what called this caller) + let parent_key = ( + step.callee_module.clone(), + step.callee_function.clone(), + step.callee_arity, + depth - 1, + ); + + let parent_index = entry_index_map.get(&parent_key).copied(); + + if filter.should_process(caller_key.clone()) && parent_index.is_some() { + let entry_idx = entries.len(); + entries.push(TraceEntry { + module: step.caller_module.clone(), + function: step.caller_function.clone(), + arity: step.caller_arity, + kind: step.caller_kind.clone(), + start_line: step.caller_start_line, + end_line: step.caller_end_line, + file: step.file.clone(), + depth, + line: step.line, + parent_index, + }); + entry_index_map.insert(caller_key, entry_idx); + } + } + } + } + + let total_items = entries.len(); + + Self { + module: target_module, + function: target_function, + max_depth, + direction: TraceDirection::Backward, + total_items, + entries, + } + } +} + +impl Execute for ReverseTraceCmd { + type Output = TraceResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let steps = reverse_trace_calls( + db, + &self.module, + &self.function, + self.arity, + &self.common.project, + self.common.regex, + self.depth, + self.common.limit, + )?; + + Ok(TraceResult::from_steps( + self.module, + self.function, + self.depth, + steps, + )) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_empty_reverse_trace() { + let result = TraceResult::from_steps( + "TestModule".to_string(), + "test_func".to_string(), + 5, + vec![], + ); + assert_eq!(result.total_items, 0); + assert_eq!(result.entries.len(), 0); + } +} diff --git a/cli/src/commands/reverse_trace/execute_tests.rs b/cli/src/commands/reverse_trace/execute_tests.rs new file mode 100644 index 0000000..082086a --- /dev/null +++ b/cli/src/commands/reverse_trace/execute_tests.rs @@ -0,0 +1,120 @@ +//! Execute tests for reverse-trace command. + +#[cfg(test)] +mod tests { + use super::super::ReverseTraceCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // At depth 1: Accounts.get_user/1, Accounts.get_user/2, Service.do_fetch all call Repo.get + crate::execute_test! { + test_name: test_reverse_trace_single_depth, + fixture: populated_db, + cmd: ReverseTraceCmd { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + arity: None, + depth: 1, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3); + // All entries at depth 1 are direct callers of the target + assert!(result.entries.iter().all(|e| e.depth == 1)); + }, + } + + // Depth 2 adds: Controller.show -> get_user, Service.fetch -> do_fetch + crate::execute_test! { + test_name: test_reverse_trace_multiple_depths, + fixture: populated_db, + cmd: ReverseTraceCmd { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + arity: None, + depth: 2, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 5); + }, + } + + // Trace back from Notifier.send_email (leaf): notify->send_email, process->notify, create->process + crate::execute_test! { + test_name: test_reverse_trace_from_leaf, + fixture: populated_db, + cmd: ReverseTraceCmd { + module: "MyApp.Notifier".to_string(), + function: "send_email".to_string(), + arity: None, + depth: 5, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_reverse_trace_no_match, + fixture: populated_db, + cmd: ReverseTraceCmd { + module: "NonExistent".to_string(), + function: "foo".to_string(), + arity: None, + depth: 5, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: entries, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: ReverseTraceCmd, + cmd: ReverseTraceCmd { + module: "MyApp".to_string(), + function: "foo".to_string(), + arity: None, + depth: 5, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/reverse_trace/mod.rs b/cli/src/commands/reverse_trace/mod.rs new file mode 100644 index 0000000..9b974b9 --- /dev/null +++ b/cli/src/commands/reverse_trace/mod.rs @@ -0,0 +1,47 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Trace call chains backwards - who calls the callers of a target +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search reverse-trace MyApp.Repo get # Who ultimately calls Repo.get? + code_search reverse-trace Ecto.Repo insert --depth 10 # Deeper traversal + code_search reverse-trace -r 'MyApp\\..*' 'handle_.*' # Regex pattern +")] +pub struct ReverseTraceCmd { + /// Target module name (exact match or pattern with --regex) + pub module: String, + + /// Target function name (exact match or pattern with --regex) + pub function: String, + + /// Function arity (optional) + #[arg(short, long)] + pub arity: Option, + + /// Maximum depth to traverse (1-20) + #[arg(long, default_value_t = 5, value_parser = clap::value_parser!(u32).range(1..=20))] + pub depth: u32, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for ReverseTraceCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/reverse_trace/output.rs b/cli/src/commands/reverse_trace/output.rs new file mode 100644 index 0000000..0d1abbc --- /dev/null +++ b/cli/src/commands/reverse_trace/output.rs @@ -0,0 +1,4 @@ +//! Output formatting for reverse-trace command results. +//! +//! The output implementation is shared with the trace command in trace/output.rs. +//! Both commands use TraceResult with a direction field to determine rendering. diff --git a/cli/src/commands/reverse_trace/output_tests.rs b/cli/src/commands/reverse_trace/output_tests.rs new file mode 100644 index 0000000..ab4cbe5 --- /dev/null +++ b/cli/src/commands/reverse_trace/output_tests.rs @@ -0,0 +1,138 @@ +//! Output formatting tests for reverse-trace command. + +#[cfg(test)] +mod tests { + use crate::types::{TraceDirection, TraceEntry, TraceResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Reverse trace to: MyApp.Repo.get +Max depth: 5 + +No callers found."; + + const SINGLE_TABLE: &str = "\ +Reverse trace to: MyApp.Repo.get +Max depth: 5 + +Found 1 caller(s) in chain: + +MyApp.Service.fetch/1 [def] (service.ex:L10:20)"; + + const MULTI_DEPTH_TABLE: &str = "\ +Reverse trace to: MyApp.Repo.get +Max depth: 5 + +Found 2 caller(s) in chain: + +MyApp.Service.fetch/1 [def] (service.ex:L10:20) + ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12)"; + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> TraceResult { + TraceResult { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + max_depth: 5, + direction: TraceDirection::Backward, + total_items: 0, + entries: vec![], + } + } + + #[fixture] + fn single_depth_result() -> TraceResult { + TraceResult { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + max_depth: 5, + direction: TraceDirection::Backward, + total_items: 1, + entries: vec![ + // Direct caller at depth 1 + TraceEntry { + module: "MyApp.Service".to_string(), + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "service.ex".to_string(), + depth: 1, + line: 15, + parent_index: None, + }, + ], + } + } + + #[fixture] + fn multi_depth_result() -> TraceResult { + TraceResult { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + max_depth: 5, + direction: TraceDirection::Backward, + total_items: 2, + entries: vec![ + TraceEntry { + module: "MyApp.Service".to_string(), + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "service.ex".to_string(), + depth: 1, + line: 15, + parent_index: None, + }, + TraceEntry { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 5, + end_line: 12, + file: "controller.ex".to_string(), + depth: 2, + line: 7, + parent_index: Some(0), + }, + ], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + #[rstest] + fn test_empty_reverse_trace(empty_result: TraceResult) { + use crate::output::Outputable; + let output = empty_result.to_table(); + assert_eq!(output, EMPTY_TABLE); + } + + #[rstest] + fn test_single_depth_reverse_trace(single_depth_result: TraceResult) { + use crate::output::Outputable; + let output = single_depth_result.to_table(); + assert_eq!(output, SINGLE_TABLE); + } + + #[rstest] + fn test_multi_depth_reverse_trace(multi_depth_result: TraceResult) { + use crate::output::Outputable; + let output = multi_depth_result.to_table(); + assert_eq!(output, MULTI_DEPTH_TABLE); + } +} diff --git a/cli/src/commands/search/cli_tests.rs b/cli/src/commands/search/cli_tests.rs new file mode 100644 index 0000000..e321f24 --- /dev/null +++ b/cli/src/commands/search/cli_tests.rs @@ -0,0 +1,92 @@ +//! CLI parsing tests for search command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use crate::commands::search::SearchKind; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "search", + test_name: test_search_requires_pattern, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "search", + variant: Search, + test_name: test_search_with_pattern, + args: ["User"], + field: pattern, + expected: "User", + } + + crate::cli_option_test! { + command: "search", + variant: Search, + test_name: test_search_with_project_filter, + args: ["User", "--project", "my_app"], + field: common.project, + expected: "my_app", + } + + crate::cli_option_test! { + command: "search", + variant: Search, + test_name: test_search_with_limit, + args: ["User", "--limit", "50"], + field: common.limit, + expected: 50, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "search", + variant: Search, + required_args: ["User"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Edge case tests (kept as regular tests due to matches! macro usage) + // ========================================================================= + + #[rstest] + fn test_search_kind_default_is_modules() { + let args = Args::try_parse_from(["code_search", "search", "test"]).unwrap(); + match args.command { + crate::commands::Command::Search(cmd) => { + assert!(matches!(cmd.kind, SearchKind::Modules)); + } + _ => panic!("Expected Search command"), + } + } + + #[rstest] + fn test_search_kind_functions() { + let args = + Args::try_parse_from(["code_search", "search", "get_", "--kind", "functions"]).unwrap(); + match args.command { + crate::commands::Command::Search(cmd) => { + assert!(matches!(cmd.kind, SearchKind::Functions)); + } + _ => panic!("Expected Search command"), + } + } +} diff --git a/cli/src/commands/search/execute.rs b/cli/src/commands/search/execute.rs new file mode 100644 index 0000000..410a224 --- /dev/null +++ b/cli/src/commands/search/execute.rs @@ -0,0 +1,93 @@ +use std::collections::BTreeMap; +use std::error::Error; + +use serde::Serialize; + +use super::{SearchCmd, SearchKind}; +use crate::commands::Execute; +use crate::queries::search::{search_functions, search_modules, FunctionResult as RawFunctionResult, ModuleResult}; + +/// A function found in search results +#[derive(Debug, Clone, Serialize)] +pub struct SearchFunc { + pub name: String, + pub arity: i64, + #[serde(skip_serializing_if = "String::is_empty")] + pub return_type: String, +} + +/// A module containing functions in search results +#[derive(Debug, Clone, Serialize)] +pub struct SearchFuncModule { + pub name: String, + pub functions: Vec, +} + +/// Result of the search command execution +#[derive(Debug, Default, Serialize)] +pub struct SearchResult { + pub pattern: String, + pub kind: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub modules: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub total_functions: Option, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub function_modules: Vec, +} + +impl SearchResult { + /// Build grouped function result from flat list + fn from_functions(pattern: String, functions: Vec) -> Self { + let total = functions.len(); + + // Group by module (BTreeMap for consistent ordering) + let mut module_map: BTreeMap> = BTreeMap::new(); + + for func in functions { + let search_func = SearchFunc { + name: func.name, + arity: func.arity, + return_type: func.return_type, + }; + + module_map.entry(func.module).or_default().push(search_func); + } + + let function_modules: Vec = module_map + .into_iter() + .map(|(name, functions)| SearchFuncModule { name, functions }) + .collect(); + + SearchResult { + pattern, + kind: "functions".to_string(), + modules: vec![], + total_functions: if total > 0 { Some(total) } else { None }, + function_modules, + } + } +} + +impl Execute for SearchCmd { + type Output = SearchResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + match self.kind { + SearchKind::Modules => { + let modules = search_modules(db, &self.pattern, &self.common.project, self.common.limit, self.common.regex)?; + Ok(SearchResult { + pattern: self.pattern, + kind: "modules".to_string(), + modules, + total_functions: None, + function_modules: vec![], + }) + } + SearchKind::Functions => { + let functions = search_functions(db, &self.pattern, &self.common.project, self.common.limit, self.common.regex)?; + Ok(SearchResult::from_functions(self.pattern, functions)) + } + } + } +} \ No newline at end of file diff --git a/cli/src/commands/search/execute_tests.rs b/cli/src/commands/search/execute_tests.rs new file mode 100644 index 0000000..2bb5361 --- /dev/null +++ b/cli/src/commands/search/execute_tests.rs @@ -0,0 +1,204 @@ +//! Execute tests for search command. + +#[cfg(test)] +mod tests { + use super::super::{SearchCmd, SearchKind}; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: type_signatures, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // 3 modules in type_signatures: Accounts, Users, Repo + crate::execute_test! { + test_name: test_search_modules_all, + fixture: populated_db, + cmd: SearchCmd { + pattern: "MyApp".to_string(), + kind: SearchKind::Modules, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.kind, "modules"); + assert_eq!(result.modules.len(), 3); + }, + } + + // Functions with "user": get_user/1, get_user/2, list_users, create_user = 4 + crate::execute_test! { + test_name: test_search_functions_all, + fixture: populated_db, + cmd: SearchCmd { + pattern: "user".to_string(), + kind: SearchKind::Functions, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.kind, "functions"); + assert_eq!(result.total_functions, Some(4)); + }, + } + + // Functions containing "get": get_user/1, get_user/2, get_by_email, Repo.get = 4 + crate::execute_test! { + test_name: test_search_functions_specific, + fixture: populated_db, + cmd: SearchCmd { + pattern: "get".to_string(), + kind: SearchKind::Functions, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_functions, Some(4)); + }, + } + + crate::execute_test! { + test_name: test_search_functions_with_regex, + fixture: populated_db, + cmd: SearchCmd { + pattern: "^get_user$".to_string(), + kind: SearchKind::Functions, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_functions, Some(2)); + // All functions should be named get_user + for module in &result.function_modules { + for f in &module.functions { + assert_eq!(f.name, "get_user"); + } + } + }, + } + + // Modules ending in Accounts or Users + crate::execute_test! { + test_name: test_search_modules_with_regex, + fixture: populated_db, + cmd: SearchCmd { + pattern: "\\.(Accounts|Users)$".to_string(), + kind: SearchKind::Modules, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.modules.len(), 2); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_search_modules_no_match, + fixture: populated_db, + cmd: SearchCmd { + pattern: "NonExistent".to_string(), + kind: SearchKind::Modules, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: modules, + } + + crate::execute_no_match_test! { + test_name: test_search_regex_no_match, + fixture: populated_db, + cmd: SearchCmd { + pattern: "^xyz".to_string(), + kind: SearchKind::Functions, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + empty_field: function_modules, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_all_match_test! { + test_name: test_search_modules_with_project_filter, + fixture: populated_db, + cmd: SearchCmd { + pattern: "App".to_string(), + kind: SearchKind::Modules, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + collection: modules, + condition: |m| m.project == "test_project", + } + + crate::execute_test! { + test_name: test_search_with_limit, + fixture: populated_db, + cmd: SearchCmd { + pattern: "user".to_string(), + kind: SearchKind::Functions, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 1, + }, + }, + assertions: |result| { + // Limit applies to raw results before grouping + assert_eq!(result.total_functions, Some(1)); + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: SearchCmd, + cmd: SearchCmd { + pattern: "test".to_string(), + kind: SearchKind::Modules, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/search/mod.rs b/cli/src/commands/search/mod.rs new file mode 100644 index 0000000..3b4c2fa --- /dev/null +++ b/cli/src/commands/search/mod.rs @@ -0,0 +1,50 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::{Args, ValueEnum}; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// What to search for +#[derive(Debug, Clone, Copy, Default, ValueEnum)] +pub enum SearchKind { + /// Search for modules + #[default] + Modules, + /// Search for functions + Functions, +} + +/// Search for modules or functions by name pattern +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search search User # Find modules containing 'User' + code_search search get_ -k functions # Find functions starting with 'get_' + code_search search -r '^MyApp\\.API' # Regex match for module prefix +")] +pub struct SearchCmd { + /// Pattern to search for (substring match by default, regex with --regex) + pub pattern: String, + + /// What to search for + #[arg(short, long, value_enum, default_value_t = SearchKind::Modules)] + pub kind: SearchKind, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for SearchCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/search/output.rs b/cli/src/commands/search/output.rs new file mode 100644 index 0000000..b147d3c --- /dev/null +++ b/cli/src/commands/search/output.rs @@ -0,0 +1,48 @@ +//! Output formatting for search command results. + +use crate::output::Outputable; +use super::execute::SearchResult; + +impl Outputable for SearchResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + lines.push(format!("Search: {} ({})", self.pattern, self.kind)); + lines.push(String::new()); + + if !self.modules.is_empty() { + lines.push(format!("Modules ({}):", self.modules.len())); + for m in &self.modules { + lines.push(format!(" {}", m.name)); + } + } + + if !self.function_modules.is_empty() { + let total = self.total_functions.unwrap_or(0); + lines.push(format!( + "Functions ({}) in {} module(s):", + total, + self.function_modules.len() + )); + lines.push(String::new()); + + for module in &self.function_modules { + lines.push(format!("{}:", module.name)); + for f in &module.functions { + let sig = if f.return_type.is_empty() { + format!("{}/{}", f.name, f.arity) + } else { + format!("{}/{} -> {}", f.name, f.arity, f.return_type) + }; + lines.push(format!(" {}", sig)); + } + } + } + + if self.modules.is_empty() && self.function_modules.is_empty() { + lines.push("No results found.".to_string()); + } + + lines.join("\n") + } +} diff --git a/cli/src/commands/search/output_tests.rs b/cli/src/commands/search/output_tests.rs new file mode 100644 index 0000000..8a5785a --- /dev/null +++ b/cli/src/commands/search/output_tests.rs @@ -0,0 +1,137 @@ +//! Output formatting tests for search command. + +#[cfg(test)] +mod tests { + use super::super::execute::{SearchFunc, SearchFuncModule, SearchResult}; + use crate::queries::search::ModuleResult; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Search: test (modules) + +No results found."; + + const MODULES_TABLE: &str = "\ +Search: MyApp (modules) + +Modules (2): + MyApp.Accounts + MyApp.Users"; + + const FUNCTIONS_TABLE: &str = "\ +Search: get_ (functions) + +Functions (1) in 1 module(s): + +MyApp.Accounts: + get_user/1 -> User.t()"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> SearchResult { + SearchResult { + pattern: "test".to_string(), + kind: "modules".to_string(), + modules: vec![], + total_functions: None, + function_modules: vec![], + } + } + + #[fixture] + fn modules_result() -> SearchResult { + SearchResult { + pattern: "MyApp".to_string(), + kind: "modules".to_string(), + modules: vec![ + ModuleResult { + project: "default".to_string(), + name: "MyApp.Accounts".to_string(), + source: "unknown".to_string(), + }, + ModuleResult { + project: "default".to_string(), + name: "MyApp.Users".to_string(), + source: "unknown".to_string(), + }, + ], + total_functions: None, + function_modules: vec![], + } + } + + #[fixture] + fn functions_result() -> SearchResult { + SearchResult { + pattern: "get_".to_string(), + kind: "functions".to_string(), + modules: vec![], + total_functions: Some(1), + function_modules: vec![SearchFuncModule { + name: "MyApp.Accounts".to_string(), + functions: vec![SearchFunc { + name: "get_user".to_string(), + arity: 1, + return_type: "User.t()".to_string(), + }], + }], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: SearchResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_modules, + fixture: modules_result, + fixture_type: SearchResult, + expected: MODULES_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_functions, + fixture: functions_result, + fixture_type: SearchResult, + expected: FUNCTIONS_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: modules_result, + fixture_type: SearchResult, + expected: crate::test_utils::load_output_fixture("search", "modules.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: modules_result, + fixture_type: SearchResult, + expected: crate::test_utils::load_output_fixture("search", "modules.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: SearchResult, + expected: crate::test_utils::load_output_fixture("search", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/commands/setup/execute.rs b/cli/src/commands/setup/execute.rs new file mode 100644 index 0000000..ee80a88 --- /dev/null +++ b/cli/src/commands/setup/execute.rs @@ -0,0 +1,887 @@ +use std::error::Error; +use std::fs; +use cozo::DbInstance; +use include_dir::{include_dir, Dir}; +use serde::Serialize; + +use super::SetupCmd; +use crate::commands::Execute; +use crate::queries::schema; + +/// Embedded skill templates directory +static SKILL_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/skills"); + +/// Embedded agent templates directory +static AGENT_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/agents"); + +/// Embedded hook templates directory +static HOOK_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/hooks"); + +/// Status of a database relation (table) +#[derive(Debug, Clone, Serialize)] +pub enum RelationState { + #[serde(rename = "created")] + Created, + #[serde(rename = "exists")] + AlreadyExists, + #[serde(rename = "would_create")] + WouldCreate, +} + +/// Status information for a single database relation +#[derive(Debug, Clone, Serialize)] +pub struct RelationStatus { + pub name: String, + pub status: RelationState, +} + +/// Status of a template file (skill or agent) +#[derive(Debug, Clone, Serialize)] +pub enum TemplateFileState { + #[serde(rename = "installed")] + Installed, + #[serde(rename = "skipped")] + Skipped, + #[serde(rename = "overwritten")] + Overwritten, +} + +/// Status information for a single template file +#[derive(Debug, Clone, Serialize)] +pub struct TemplateFileStatus { + pub path: String, + pub status: TemplateFileState, +} + +/// Result of templates installation +#[derive(Debug, Serialize)] +pub struct TemplatesInstallResult { + pub skills: Vec, + pub agents: Vec, + pub skills_installed: usize, + pub skills_skipped: usize, + pub skills_overwritten: usize, + pub agents_installed: usize, + pub agents_skipped: usize, + pub agents_overwritten: usize, +} + +/// Result of git hooks installation +#[derive(Debug, Serialize)] +pub struct HooksInstallResult { + pub hooks: Vec, + pub hooks_installed: usize, + pub hooks_skipped: usize, + pub hooks_overwritten: usize, + pub git_config: Vec, +} + +/// Status of a git config setting +#[derive(Debug, Clone, Serialize)] +pub struct GitConfigStatus { + pub key: String, + pub value: String, + pub set: bool, +} + +/// Result of the setup command execution +#[derive(Debug, Serialize)] +pub struct SetupResult { + pub relations: Vec, + pub created_new: bool, + pub dry_run: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub templates: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub hooks: Option, +} + +/// Recursively process a directory and install all files +fn process_dir( + dir: &include_dir::Dir, + base_path: &std::path::Path, + force: bool, + files: &mut Vec, + installed_count: &mut usize, + skipped_count: &mut usize, + overwritten_count: &mut usize, +) -> Result<(), Box> { + for entry in dir.entries() { + match entry { + include_dir::DirEntry::Dir(subdir) => { + // Recursively process subdirectory + process_dir(subdir, base_path, force, files, installed_count, skipped_count, overwritten_count)?; + } + include_dir::DirEntry::File(file) => { + let relative_path = file.path(); + let target_path = base_path.join(relative_path); + + // Create parent directories if needed + if let Some(parent) = target_path.parent() { + fs::create_dir_all(parent)?; + } + + // Check if file exists + let exists = target_path.exists(); + let status = if exists && !force { + // Skip existing files unless force is enabled + *skipped_count += 1; + TemplateFileState::Skipped + } else { + // Write file contents + fs::write(&target_path, file.contents())?; + + if exists { + *overwritten_count += 1; + TemplateFileState::Overwritten + } else { + *installed_count += 1; + TemplateFileState::Installed + } + }; + + files.push(TemplateFileStatus { + path: relative_path.display().to_string(), + status, + }); + } + } + } + Ok(()) +} + +/// Install templates (skills and agents) to .claude/ in the given base directory +fn install_templates_to(base_dir: &std::path::Path, force: bool) -> Result> { + let claude_dir = base_dir.join(".claude"); + let skills_dir = claude_dir.join("skills"); + let agents_dir = claude_dir.join("agents"); + + // Create .claude/skills/ and .claude/agents/ directories + fs::create_dir_all(&skills_dir)?; + fs::create_dir_all(&agents_dir)?; + + // Process skills + let mut skills_files = Vec::new(); + let mut skills_installed = 0; + let mut skills_skipped = 0; + let mut skills_overwritten = 0; + + process_dir( + &SKILL_TEMPLATES, + &skills_dir, + force, + &mut skills_files, + &mut skills_installed, + &mut skills_skipped, + &mut skills_overwritten, + )?; + + // Process agents + let mut agents_files = Vec::new(); + let mut agents_installed = 0; + let mut agents_skipped = 0; + let mut agents_overwritten = 0; + + process_dir( + &AGENT_TEMPLATES, + &agents_dir, + force, + &mut agents_files, + &mut agents_installed, + &mut agents_skipped, + &mut agents_overwritten, + )?; + + Ok(TemplatesInstallResult { + skills: skills_files, + agents: agents_files, + skills_installed, + skills_skipped, + skills_overwritten, + agents_installed, + agents_skipped, + agents_overwritten, + }) +} + +/// Install templates to .claude/ +fn install_templates(force: bool) -> Result> { + // Get current working directory + let cwd = std::env::current_dir()?; + install_templates_to(&cwd, force) +} + +/// Install git hooks to .git/hooks/ +fn install_hooks( + force: bool, + project_name: Option, + mix_env: Option, +) -> Result> { + use std::process::Command; + + // Check if we're in a git repository + let git_dir = Command::new("git") + .args(["rev-parse", "--git-dir"]) + .output()?; + + if !git_dir.status.success() { + return Err("Not in a git repository".into()); + } + + let git_dir_path = String::from_utf8(git_dir.stdout)?.trim().to_string(); + let hooks_dir = std::path::Path::new(&git_dir_path).join("hooks"); + + // Create hooks directory if it doesn't exist + fs::create_dir_all(&hooks_dir)?; + + // Process hook files + let mut hooks_files = Vec::new(); + let mut hooks_installed = 0; + let mut hooks_skipped = 0; + let mut hooks_overwritten = 0; + + process_dir( + &HOOK_TEMPLATES, + &hooks_dir, + force, + &mut hooks_files, + &mut hooks_installed, + &mut hooks_skipped, + &mut hooks_overwritten, + )?; + + // Make hooks executable + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + for file_status in &hooks_files { + let hook_path = hooks_dir.join(&file_status.path); + if hook_path.exists() { + let mut perms = fs::metadata(&hook_path)?.permissions(); + perms.set_mode(0o755); + fs::set_permissions(&hook_path, perms)?; + } + } + } + + // Configure git settings + let mut git_config = Vec::new(); + + // Build config list (only set values that are provided) + let mut configs: Vec<(&str, String)> = Vec::new(); + + // Only set project name if explicitly provided + if let Some(name) = project_name { + configs.push(("code-search.project-name", name)); + } + + // Set mix-env (default to "dev" if not provided) + configs.push(( + "code-search.mix-env", + mix_env.unwrap_or_else(|| "dev".to_string()), + )); + + for (key, value) in configs { + let output = Command::new("git") + .args(["config", key, &value]) + .output()?; + + git_config.push(GitConfigStatus { + key: key.to_string(), + value, + set: output.status.success(), + }); + } + + Ok(HooksInstallResult { + hooks: hooks_files, + hooks_installed, + hooks_skipped, + hooks_overwritten, + git_config, + }) +} + +impl Execute for SetupCmd { + type Output = SetupResult; + + fn execute(self, db: &DbInstance) -> Result> { + let mut relations = Vec::new(); + + if self.dry_run { + // In dry-run mode, just show what would be created + for rel_name in schema::relation_names() { + relations.push(RelationStatus { + name: rel_name.to_string(), + status: RelationState::WouldCreate, + }); + } + + return Ok(SetupResult { + relations, + created_new: false, + dry_run: true, + templates: None, + hooks: None, + }); + } + + // Note: The --force flag only affects template and hook file overwriting. + // It does not drop and recreate database schemas. Schema creation is idempotent + // and will skip existing relations regardless of the --force flag. + + // Create schema + let schema_results = schema::create_schema(db)?; + + for schema_result in schema_results { + let status = if schema_result.created { + RelationState::Created + } else { + RelationState::AlreadyExists + }; + + relations.push(RelationStatus { + name: schema_result.relation, + status, + }); + } + + // Check if we created new relations + let created_new = relations + .iter() + .any(|r| matches!(r.status, RelationState::Created)); + + // Install templates (skills and agents) if requested + let templates = if self.install_skills { + Some(install_templates(self.force)?) + } else { + None + }; + + // Install git hooks if requested + let hooks = if self.install_hooks { + Some(install_hooks( + self.force, + self.project_name, + self.mix_env, + )?) + } else { + None + }; + + Ok(SetupResult { + relations, + created_new, + dry_run: false, + templates, + hooks, + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::db::open_db; + use rstest::{fixture, rstest}; + use tempfile::NamedTempFile; + + #[fixture] + fn db_file() -> NamedTempFile { + NamedTempFile::new().expect("Failed to create temp db file") + } + + #[rstest] + fn test_setup_creates_all_relations(db_file: NamedTempFile) { + let cmd = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db).expect("Setup should succeed"); + + // Should create 7 relations + assert_eq!(result.relations.len(), 7); + + // All should be created + assert!(result + .relations + .iter() + .all(|r| matches!(r.status, RelationState::Created))); + + assert!(result.created_new); + assert!(result.templates.is_none()); + assert!(result.hooks.is_none()); + } + + #[rstest] + fn test_setup_idempotent(db_file: NamedTempFile) { + let db = open_db(db_file.path()).expect("Failed to open db"); + + // First setup + let cmd1 = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + let result1 = cmd1.execute(&db).expect("First setup should succeed"); + assert!(result1.created_new); + + // Second setup should find existing relations + let cmd2 = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + let result2 = cmd2.execute(&db).expect("Second setup should succeed"); + + // Should still have 7 relations, but all already existing + assert_eq!(result2.relations.len(), 7); + assert!(result2 + .relations + .iter() + .all(|r| matches!(r.status, RelationState::AlreadyExists))); + + assert!(!result2.created_new); + } + + #[rstest] + fn test_setup_dry_run(db_file: NamedTempFile) { + let cmd = SetupCmd { + force: false, + dry_run: true, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db).expect("Setup should succeed"); + + assert!(result.dry_run); + assert_eq!(result.relations.len(), 7); + + // All should be in would_create state + assert!(result + .relations + .iter() + .all(|r| matches!(r.status, RelationState::WouldCreate))); + + // Should not have actually created anything + assert!(!result.created_new); + } + + #[rstest] + fn test_setup_relations_have_correct_names(db_file: NamedTempFile) { + let cmd = SetupCmd { + force: false, + dry_run: true, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db).expect("Setup should succeed"); + + let relation_names: Vec<_> = result.relations.iter().map(|r| r.name.as_str()).collect(); + + assert!(relation_names.contains(&"modules")); + assert!(relation_names.contains(&"functions")); + assert!(relation_names.contains(&"calls")); + assert!(relation_names.contains(&"struct_fields")); + assert!(relation_names.contains(&"function_locations")); + assert!(relation_names.contains(&"specs")); + assert!(relation_names.contains(&"types")); + } + + #[test] + fn test_install_templates() { + use tempfile::TempDir; + + // Create a temporary directory + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + + // Install templates directly to temp directory + let result = install_templates_to(temp_dir.path(), false) + .expect("Install should succeed"); + + // All files should be installed (not skipped or overwritten) + assert_eq!(result.skills_installed, 34, "Should install all 34 skill files"); + assert_eq!(result.skills_skipped, 0); + assert_eq!(result.skills_overwritten, 0); + + assert_eq!(result.agents_installed, 1, "Should install 1 agent file"); + assert_eq!(result.agents_skipped, 0); + assert_eq!(result.agents_overwritten, 0); + + // Verify .claude/skills and .claude/agents directories were created + assert!(temp_dir.path().join(".claude").join("skills").exists()); + assert!(temp_dir.path().join(".claude").join("agents").exists()); + } + + #[test] + fn test_install_templates_skips_existing() { + use tempfile::TempDir; + + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + + // First installation + let result1 = install_templates_to(temp_dir.path(), false) + .expect("First install should succeed"); + assert_eq!(result1.skills_installed, 34); + assert_eq!(result1.agents_installed, 1); + + // Second installation without force - should skip all files + let result2 = install_templates_to(temp_dir.path(), false) + .expect("Second install should succeed"); + assert_eq!(result2.skills_installed, 0, "Should not install any skill files"); + assert_eq!(result2.skills_skipped, 34, "Should skip all 34 existing skill files"); + assert_eq!(result2.skills_overwritten, 0); + + assert_eq!(result2.agents_installed, 0, "Should not install any agent files"); + assert_eq!(result2.agents_skipped, 1, "Should skip the existing agent file"); + assert_eq!(result2.agents_overwritten, 0); + } + + #[test] + fn test_install_templates_force_overwrites() { + use tempfile::TempDir; + + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + + // First installation + let result1 = install_templates_to(temp_dir.path(), false) + .expect("First install should succeed"); + assert_eq!(result1.skills_installed, 34); + assert_eq!(result1.agents_installed, 1); + + // Second installation with force - should overwrite all files + let result2 = install_templates_to(temp_dir.path(), true) + .expect("Second install with force should succeed"); + assert_eq!(result2.skills_installed, 0, "Should not install new skill files"); + assert_eq!(result2.skills_skipped, 0, "Should not skip any skill files"); + assert_eq!(result2.skills_overwritten, 34, "Should overwrite all 34 existing skill files"); + + assert_eq!(result2.agents_installed, 0, "Should not install new agent files"); + assert_eq!(result2.agents_skipped, 0, "Should not skip any agent files"); + assert_eq!(result2.agents_overwritten, 1, "Should overwrite the existing agent file"); + } + + #[rstest] + fn test_no_templates_when_not_requested(db_file: NamedTempFile) { + let cmd = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: false, + project_name: None, + mix_env: None, + }; + + let db = open_db(db_file.path()).expect("Failed to open db"); + let result = cmd.execute(&db).expect("Setup should succeed"); + + // Templates and hooks should be None when not requested + assert!(result.templates.is_none()); + assert!(result.hooks.is_none()); + } + + #[test] + #[serial_test::serial] + fn test_install_hooks_in_git_repo() { + use std::process::Command; + use tempfile::TempDir; + + // Create a temporary directory and initialize a git repo + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + let temp_path = temp_dir.path(); + + // Initialize git repo + Command::new("git") + .args(["init"]) + .current_dir(temp_path) + .output() + .expect("Failed to initialize git repo"); + + // Change to the temp directory for the test + let original_dir = std::env::current_dir().expect("Failed to get current dir"); + std::env::set_current_dir(temp_path).expect("Failed to change directory"); + + // Create a temporary database + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let cmd = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: Some("test_project".to_string()), + mix_env: Some("test".to_string()), + }; + + let result = cmd.execute(&db).expect("Setup with hooks should succeed"); + + // Verify hook file exists and is executable BEFORE restoring directory + let hook_path = temp_path.join(".git").join("hooks").join("post-commit"); + assert!(hook_path.exists(), "Hook file should exist"); + + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let metadata = fs::metadata(&hook_path).expect("Failed to get hook metadata"); + let permissions = metadata.permissions(); + assert!( + permissions.mode() & 0o111 != 0, + "Hook should be executable" + ); + } + + // Verify hook content + let hook_content = fs::read_to_string(&hook_path).expect("Failed to read hook"); + assert!(hook_content.contains("#!/usr/bin/env bash")); + assert!(hook_content.contains("ex_ast --git-diff")); + assert!(hook_content.contains("code_search")); + assert!(hook_content.contains("GIT_REF")); // Uses variable for git reference + + // Verify hooks were installed + assert!(result.hooks.is_some()); + let hooks = result.hooks.unwrap(); + + // Should have installed 1 hook (post-commit) + assert_eq!(hooks.hooks_installed, 1); + assert_eq!(hooks.hooks_skipped, 0); + assert_eq!(hooks.hooks_overwritten, 0); + + // Should have 1 hook file + assert_eq!(hooks.hooks.len(), 1); + assert_eq!(hooks.hooks[0].path, "post-commit"); + assert!(matches!(hooks.hooks[0].status, TemplateFileState::Installed)); + + // Should have configured 2 git settings (project-name and mix-env) + assert_eq!(hooks.git_config.len(), 2); + + // Verify git config values + let project_config = hooks.git_config.iter().find(|c| c.key == "code-search.project-name"); + assert!(project_config.is_some()); + assert_eq!(project_config.unwrap().value, "test_project"); + assert!(project_config.unwrap().set); + + let mix_env_config = hooks.git_config.iter().find(|c| c.key == "code-search.mix-env"); + assert!(mix_env_config.is_some()); + assert_eq!(mix_env_config.unwrap().value, "test"); + assert!(mix_env_config.unwrap().set); + + // Restore original directory + std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted + } + + #[test] + #[serial_test::serial] + fn test_install_hooks_with_defaults() { + use std::process::Command; + use tempfile::TempDir; + + // Create a temporary directory and initialize a git repo + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + let temp_path = temp_dir.path(); + + Command::new("git") + .args(["init"]) + .current_dir(temp_path) + .output() + .expect("Failed to initialize git repo"); + + let original_dir = std::env::current_dir().expect("Failed to get current dir"); + std::env::set_current_dir(temp_path).expect("Failed to change directory"); + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let cmd = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + let result = cmd.execute(&db).expect("Setup with hooks should succeed"); + + assert!(result.hooks.is_some()); + let hooks = result.hooks.unwrap(); + + // Should only set mix-env (project-name not set when None) + assert_eq!(hooks.git_config.len(), 1); + + // Verify default values were used + let mix_env_config = hooks.git_config.iter().find(|c| c.key == "code-search.mix-env"); + assert!(mix_env_config.is_some()); + assert_eq!(mix_env_config.unwrap().value, "dev"); + + // Verify project-name was NOT set + let project_config = hooks.git_config.iter().find(|c| c.key == "code-search.project-name"); + assert!(project_config.is_none()); + + // Restore original directory + std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted + } + + #[test] + #[serial_test::serial] + fn test_install_hooks_skips_existing() { + use std::process::Command; + use tempfile::TempDir; + + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + let temp_path = temp_dir.path(); + + Command::new("git") + .args(["init"]) + .current_dir(temp_path) + .output() + .expect("Failed to initialize git repo"); + + let original_dir = std::env::current_dir().expect("Failed to get current dir"); + std::env::set_current_dir(temp_path).expect("Failed to change directory"); + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + // First installation + let cmd1 = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + let result1 = cmd1.execute(&db).expect("First install should succeed"); + assert_eq!(result1.hooks.as_ref().unwrap().hooks_installed, 1); + + // Second installation without force + let cmd2 = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + let result2 = cmd2.execute(&db).expect("Second install should succeed"); + + // Should skip existing hook + assert_eq!(result2.hooks.as_ref().unwrap().hooks_installed, 0); + assert_eq!(result2.hooks.as_ref().unwrap().hooks_skipped, 1); + assert_eq!(result2.hooks.as_ref().unwrap().hooks_overwritten, 0); + + // Restore original directory + std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted + } + + #[test] + #[serial_test::serial] + fn test_install_hooks_force_overwrites() { + use std::process::Command; + use tempfile::TempDir; + + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + let temp_path = temp_dir.path(); + + Command::new("git") + .args(["init"]) + .current_dir(temp_path) + .output() + .expect("Failed to initialize git repo"); + + let original_dir = std::env::current_dir().expect("Failed to get current dir"); + std::env::set_current_dir(temp_path).expect("Failed to change directory"); + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + // First installation + let cmd1 = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + cmd1.execute(&db).expect("First install should succeed"); + + // Second installation with force + let cmd2 = SetupCmd { + force: true, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + let result2 = cmd2.execute(&db).expect("Second install with force should succeed"); + + // Should overwrite existing hook + assert_eq!(result2.hooks.as_ref().unwrap().hooks_installed, 0); + assert_eq!(result2.hooks.as_ref().unwrap().hooks_skipped, 0); + assert_eq!(result2.hooks.as_ref().unwrap().hooks_overwritten, 1); + + // Restore original directory + std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted + } + + #[test] + #[serial_test::serial] + fn test_install_hooks_fails_outside_git_repo() { + use tempfile::TempDir; + + let temp_dir = TempDir::new().expect("Failed to create temp dir"); + let temp_path = temp_dir.path(); + + let original_dir = std::env::current_dir().expect("Failed to get current dir"); + std::env::set_current_dir(temp_path).expect("Failed to change directory"); + + let db_file = NamedTempFile::new().expect("Failed to create temp db file"); + let db = open_db(db_file.path()).expect("Failed to open db"); + + let cmd = SetupCmd { + force: false, + dry_run: false, + install_skills: false, + install_hooks: true, + project_name: None, + mix_env: None, + }; + + let result = cmd.execute(&db); + + // Restore original directory + std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted + + // Should fail because we're not in a git repo + assert!(result.is_err()); + let err_msg = result.unwrap_err().to_string(); + assert!(err_msg.contains("Not in a git repository")); + } +} diff --git a/cli/src/commands/setup/mod.rs b/cli/src/commands/setup/mod.rs new file mode 100644 index 0000000..463dac9 --- /dev/null +++ b/cli/src/commands/setup/mod.rs @@ -0,0 +1,54 @@ +mod execute; +mod output; + +use std::error::Error; +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Create database schema without importing data +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search setup # Create schema in .code_search/cozo.sqlite + code_search setup --force # Overwrite existing templates/hooks + code_search setup --dry-run # Show what would be created + code_search setup --install-skills # Create schema and install skill templates + code_search setup --install-skills --force # Overwrite existing skill files + code_search setup --install-hooks # Install git hooks for incremental updates + code_search setup --install-hooks --project-name my_app # Configure project name + code_search setup --install-skills --install-hooks # Install both skills and hooks")] +pub struct SetupCmd { + /// Overwrite existing template and hook files (does not affect schema) + #[arg(long, default_value_t = false)] + pub force: bool, + + /// Show what would be created without doing it + #[arg(long, default_value_t = false)] + pub dry_run: bool, + + /// Install skill templates to .claude/skills/ + #[arg(long, default_value_t = false)] + pub install_skills: bool, + + /// Install git hooks for incremental database updates + #[arg(long, default_value_t = false)] + pub install_hooks: bool, + + /// Project name to configure in git hooks (only used with --install-hooks) + #[arg(long)] + pub project_name: Option, + + /// Mix environment to configure in git hooks (defaults to 'dev', only used with --install-hooks) + #[arg(long)] + pub mix_env: Option, +} + +impl CommandRunner for SetupCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/setup/output.rs b/cli/src/commands/setup/output.rs new file mode 100644 index 0000000..3a588d8 --- /dev/null +++ b/cli/src/commands/setup/output.rs @@ -0,0 +1,189 @@ +//! Output formatting for setup command results. + +use crate::output::Outputable; +use crate::commands::setup::execute::{SetupResult, RelationState, TemplateFileState}; + +impl Outputable for SetupResult { + fn to_table(&self) -> String { + let mut output = String::new(); + + output.push_str("Database Setup\n\n"); + + if self.dry_run { + output.push_str("Schema creation (dry-run):\n"); + } else { + output.push_str("Schema creation:\n"); + } + + for relation in &self.relations { + let symbol = match relation.status { + RelationState::Created => "✓", + RelationState::AlreadyExists => "✓", + RelationState::WouldCreate => "→", + }; + + let status_text = match relation.status { + RelationState::Created => "created", + RelationState::AlreadyExists => "exists", + RelationState::WouldCreate => "would create", + }; + + output.push_str(&format!(" {} {} ({})\n", symbol, relation.name, status_text)); + } + + if self.dry_run { + output.push_str("\nNo changes made (dry-run mode).\n"); + } else if self.created_new { + output.push_str("\nDatabase ready.\n"); + } else { + output.push_str("\nDatabase already configured.\n"); + } + + // Add template installation results if present + if let Some(ref templates) = self.templates { + output.push_str("\nTemplates Installation:\n"); + + // Skills summary + let total_skills = templates.skills_installed + templates.skills_skipped + templates.skills_overwritten; + if total_skills > 0 { + output.push_str("\n Skills:\n"); + output.push_str(&format!( + " Installed: {}, Skipped: {}, Overwritten: {}\n", + templates.skills_installed, templates.skills_skipped, templates.skills_overwritten + )); + + // Group skill files by status + let installed: Vec<_> = templates + .skills + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Installed)) + .collect(); + let overwritten: Vec<_> = templates + .skills + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) + .collect(); + let _skipped: Vec<_> = templates + .skills + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Skipped)) + .collect(); + + // Show installed skills (only first few) + if !installed.is_empty() { + let show_count = installed.len().min(5); + for file in &installed[..show_count] { + output.push_str(&format!(" ✓ {}\n", file.path)); + } + if installed.len() > show_count { + output.push_str(&format!(" ... and {} more\n", installed.len() - show_count)); + } + } + + // Show overwritten skills + if !overwritten.is_empty() { + let show_count = overwritten.len().min(3); + for file in &overwritten[..show_count] { + output.push_str(&format!(" ⟳ {}\n", file.path)); + } + if overwritten.len() > show_count { + output.push_str(&format!(" ... and {} more overwritten\n", overwritten.len() - show_count)); + } + } + } + + // Agents summary + let total_agents = templates.agents_installed + templates.agents_skipped + templates.agents_overwritten; + if total_agents > 0 { + output.push_str("\n Agents:\n"); + output.push_str(&format!( + " Installed: {}, Skipped: {}, Overwritten: {}\n", + templates.agents_installed, templates.agents_skipped, templates.agents_overwritten + )); + + // Group agent files by status + let installed: Vec<_> = templates + .agents + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Installed)) + .collect(); + let overwritten: Vec<_> = templates + .agents + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) + .collect(); + + // Show installed agents + if !installed.is_empty() { + for file in installed { + output.push_str(&format!(" ✓ {}\n", file.path)); + } + } + + // Show overwritten agents + if !overwritten.is_empty() { + for file in overwritten { + output.push_str(&format!(" ⟳ {}\n", file.path)); + } + } + } + + output.push_str("\nTemplates installed to .claude/\n"); + } + + // Add git hooks installation results if present + if let Some(ref hooks) = self.hooks { + output.push_str("\nGit Hooks Installation:\n"); + + // Hooks summary + let total_hooks = hooks.hooks_installed + hooks.hooks_skipped + hooks.hooks_overwritten; + if total_hooks > 0 { + output.push_str(&format!( + "\n Installed: {}, Skipped: {}, Overwritten: {}\n", + hooks.hooks_installed, hooks.hooks_skipped, hooks.hooks_overwritten + )); + + // Show hooks by status + let installed: Vec<_> = hooks + .hooks + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Installed)) + .collect(); + let overwritten: Vec<_> = hooks + .hooks + .iter() + .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) + .collect(); + + if !installed.is_empty() { + for file in installed { + output.push_str(&format!(" ✓ {}\n", file.path)); + } + } + + if !overwritten.is_empty() { + for file in overwritten { + output.push_str(&format!(" ⟳ {}\n", file.path)); + } + } + } + + // Git config + if !hooks.git_config.is_empty() { + output.push_str("\n Git Configuration:\n"); + for config in &hooks.git_config { + let symbol = if config.set { "✓" } else { "✗" }; + output.push_str(&format!( + " {} {} = {}\n", + symbol, config.key, config.value + )); + } + } + + output.push_str("\nGit hooks installed to .git/hooks/\n"); + output.push_str("Run 'git config --get-regexp code-search' to view configuration.\n"); + } + + output + } +} diff --git a/cli/src/commands/struct_usage/cli_tests.rs b/cli/src/commands/struct_usage/cli_tests.rs new file mode 100644 index 0000000..87d0eda --- /dev/null +++ b/cli/src/commands/struct_usage/cli_tests.rs @@ -0,0 +1,91 @@ +//! CLI parsing tests for struct-usage command. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "struct-usage", + test_name: test_requires_pattern, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_with_pattern, + args: ["User.t"], + field: pattern, + expected: "User.t", + } + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_with_module, + args: ["User.t", "MyApp.Accounts"], + field: module, + expected: Some("MyApp.Accounts".to_string()), + } + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_with_by_module, + args: ["User.t", "--by-module"], + field: by_module, + expected: true, + } + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_by_module_default_false, + args: ["User.t"], + field: by_module, + expected: false, + } + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_with_regex, + args: [".*\\.t", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "struct-usage", + variant: StructUsage, + test_name: test_with_limit, + args: ["User.t", "--limit", "50"], + field: common.limit, + expected: 50, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "struct-usage", + variant: StructUsage, + required_args: ["User.t"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } +} diff --git a/cli/src/commands/struct_usage/execute.rs b/cli/src/commands/struct_usage/execute.rs new file mode 100644 index 0000000..6175720 --- /dev/null +++ b/cli/src/commands/struct_usage/execute.rs @@ -0,0 +1,177 @@ +use std::collections::{BTreeMap, HashSet}; +use std::error::Error; + +use serde::Serialize; + +use super::StructUsageCmd; +use crate::commands::Execute; +use crate::queries::struct_usage::{find_struct_usage, StructUsageEntry}; +use crate::types::ModuleGroupResult; + +/// A function that uses a struct type +#[derive(Debug, Clone, Serialize)] +pub struct UsageInfo { + pub name: String, + pub arity: i64, + pub inputs: String, + pub returns: String, + pub line: i64, +} + +/// A module and its usage counts for a struct type +#[derive(Debug, Clone, Serialize)] +pub struct ModuleStructUsage { + pub name: String, + pub accepts_count: i64, + pub returns_count: i64, + pub total: i64, +} + +/// Result containing aggregated module-level struct usage +#[derive(Debug, Clone, Serialize)] +pub struct StructModulesResult { + pub struct_pattern: String, + pub total_modules: usize, + pub total_functions: usize, + pub modules: Vec, +} + +/// Output type that can be either detailed or aggregated +#[derive(Debug, Serialize)] +#[serde(untagged)] +pub enum StructUsageOutput { + Detailed(ModuleGroupResult), + ByModule(StructModulesResult), +} + +impl ModuleGroupResult { + /// Build grouped result from flat StructUsageEntry list + fn from_entries( + pattern: String, + module_filter: Option, + entries: Vec, + ) -> Self { + let total_items = entries.len(); + + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let usage_info = UsageInfo { + name: entry.name, + arity: entry.arity, + inputs: entry.inputs_string, + returns: entry.return_string, + line: entry.line, + }; + (entry.module, usage_info) + }); + + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, + } + } +} + +impl StructModulesResult { + /// Build aggregated result from flat StructUsageEntry list + fn from_entries(pattern: String, entries: Vec) -> Self { + // Aggregate by module, tracking which functions accept vs return + let mut module_map: BTreeMap> = BTreeMap::new(); + let mut module_accepts: BTreeMap> = BTreeMap::new(); + let mut module_returns: BTreeMap> = BTreeMap::new(); + + for entry in &entries { + // Track unique functions per module + module_map + .entry(entry.module.clone()) + .or_default() + .insert(format!("{}/{}", entry.name, entry.arity)); + + // Check if function accepts the type + if entry.inputs_string.contains(&pattern) { + module_accepts + .entry(entry.module.clone()) + .or_default() + .insert(format!("{}/{}", entry.name, entry.arity)); + } + + // Check if function returns the type + if entry.return_string.contains(&pattern) { + module_returns + .entry(entry.module.clone()) + .or_default() + .insert(format!("{}/{}", entry.name, entry.arity)); + } + } + + // Convert to result type, sorted by total count descending + let mut modules: Vec = module_map + .into_iter() + .map(|(name, functions)| { + let accepts_count = module_accepts + .get(&name) + .map(|s| s.len() as i64) + .unwrap_or(0); + let returns_count = module_returns + .get(&name) + .map(|s| s.len() as i64) + .unwrap_or(0); + let total = functions.len() as i64; + + ModuleStructUsage { + name, + accepts_count, + returns_count, + total, + } + }) + .collect(); + + // Sort by total count descending, then by module name + modules.sort_by(|a, b| { + let cmp = b.total.cmp(&a.total); + if cmp == std::cmp::Ordering::Equal { + a.name.cmp(&b.name) + } else { + cmp + } + }); + + let total_modules = modules.len(); + let total_functions = entries.len(); + + StructModulesResult { + struct_pattern: pattern, + total_modules, + total_functions, + modules, + } + } +} + +impl Execute for StructUsageCmd { + type Output = StructUsageOutput; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let entries = find_struct_usage( + db, + &self.pattern, + &self.common.project, + self.common.regex, + self.module.as_deref(), + self.common.limit, + )?; + + if self.by_module { + Ok(StructUsageOutput::ByModule( + StructModulesResult::from_entries(self.pattern, entries), + )) + } else { + Ok(StructUsageOutput::Detailed( + ModuleGroupResult::::from_entries(self.pattern, self.module, entries), + )) + } + } +} diff --git a/cli/src/commands/struct_usage/execute_tests.rs b/cli/src/commands/struct_usage/execute_tests.rs new file mode 100644 index 0000000..9874cc1 --- /dev/null +++ b/cli/src/commands/struct_usage/execute_tests.rs @@ -0,0 +1,228 @@ +//! Execute tests for struct-usage command. + +#[cfg(test)] +mod tests { + use super::super::StructUsageCmd; + use super::super::execute::StructUsageOutput; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: type_signatures, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests - Detailed mode + // ========================================================================= + + // The type_signatures fixture has User.t() in returns for: + // - MyApp.Accounts: get_user/1, get_user/2, list_users/0, create_user/1 + // - MyApp.Users: get_by_email/1, authenticate/2 + crate::execute_test! { + test_name: test_struct_usage_finds_user_type, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "User.t".to_string(), + module: None, + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::Detailed(ref detail) => { + assert!(detail.total_items > 0, "Should find functions using User.t"); + // Should have entries from at least 2 modules + assert!(detail.items.len() >= 2, "Should find User.t in multiple modules"); + } + _ => panic!("Expected Detailed output"), + } + }, + } + + crate::execute_test! { + test_name: test_struct_usage_with_module_filter, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "User.t".to_string(), + module: Some("MyApp.Accounts".to_string()), + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::Detailed(ref detail) => { + assert!(detail.total_items > 0, "Should find functions in MyApp.Accounts"); + // All results should be from MyApp.Accounts + for module_group in &detail.items { + assert_eq!(module_group.name, "MyApp.Accounts"); + } + } + _ => panic!("Expected Detailed output"), + } + }, + } + + // ========================================================================= + // Core functionality tests - ByModule mode + // ========================================================================= + + crate::execute_test! { + test_name: test_struct_usage_by_module, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "User.t".to_string(), + module: None, + by_module: true, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::ByModule(ref by_module) => { + assert!(by_module.total_modules > 0, "Should find modules using User.t"); + assert!(by_module.total_functions > 0, "Should have function count"); + // Each module should have counts + for module in &by_module.modules { + assert!(module.total > 0, "Module should have at least one function"); + } + } + _ => panic!("Expected ByModule output"), + } + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_test! { + test_name: test_struct_usage_no_match, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "NonExistentType.t".to_string(), + module: None, + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::Detailed(ref detail) => { + assert!(detail.items.is_empty(), "Should find no matches"); + assert_eq!(detail.total_items, 0); + } + _ => panic!("Expected Detailed output"), + } + }, + } + + crate::execute_test! { + test_name: test_struct_usage_by_module_no_match, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "NonExistentType.t".to_string(), + module: None, + by_module: true, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::ByModule(ref by_module) => { + assert!(by_module.modules.is_empty(), "Should find no modules"); + assert_eq!(by_module.total_modules, 0); + assert_eq!(by_module.total_functions, 0); + } + _ => panic!("Expected ByModule output"), + } + }, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_struct_usage_with_limit, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: "User.t".to_string(), + module: None, + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 1, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::Detailed(ref detail) => { + assert_eq!(detail.total_items, 1, "Limit should restrict to 1 result"); + } + _ => panic!("Expected Detailed output"), + } + }, + } + + crate::execute_test! { + test_name: test_struct_usage_regex_pattern, + fixture: populated_db, + cmd: StructUsageCmd { + pattern: ".*\\.t\\(\\)".to_string(), + module: None, + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + match result { + StructUsageOutput::Detailed(ref detail) => { + // Should match User.t(), Ecto.Changeset.t(), etc. + assert!(detail.total_items > 0, "Regex should match .t() types"); + } + _ => panic!("Expected Detailed output"), + } + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: StructUsageCmd, + cmd: StructUsageCmd { + pattern: "User.t".to_string(), + module: None, + by_module: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/struct_usage/mod.rs b/cli/src/commands/struct_usage/mod.rs new file mode 100644 index 0000000..a1c4f13 --- /dev/null +++ b/cli/src/commands/struct_usage/mod.rs @@ -0,0 +1,49 @@ +mod execute; +mod output; + +#[cfg(test)] +mod cli_tests; +#[cfg(test)] +mod execute_tests; +#[cfg(test)] +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions that accept or return a specific type pattern +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search struct-usage \"User.t\" # Find functions using User.t + code_search struct-usage \"Changeset.t\" # Find functions using Changeset.t + code_search struct-usage \"User.t\" MyApp # Filter to module MyApp + code_search struct-usage \"User.t\" --by-module # Summarize by module + code_search struct-usage -r \".*\\.t\" # Regex pattern matching +")] +pub struct StructUsageCmd { + /// Type pattern to search for in both inputs and returns + pub pattern: String, + + /// Module filter pattern + pub module: Option, + + /// Aggregate results by module (show counts instead of function details) + #[arg(long)] + pub by_module: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for StructUsageCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/struct_usage/output.rs b/cli/src/commands/struct_usage/output.rs new file mode 100644 index 0000000..a430ee2 --- /dev/null +++ b/cli/src/commands/struct_usage/output.rs @@ -0,0 +1,140 @@ +//! Output formatting for struct-usage command results. + +use regex::Regex; +use std::sync::LazyLock; + +use crate::output::{Outputable, TableFormatter}; +use crate::types::ModuleGroupResult; +use super::execute::{UsageInfo, StructUsageOutput, StructModulesResult}; + +/// Regex to match Elixir struct maps like `%{__struct__: Module.Name, field: type(), ...}` +static STRUCT_MAP_REGEX: LazyLock = LazyLock::new(|| { + Regex::new(r"%\{__struct__:\s*([A-Za-z][A-Za-z0-9_.]*),\s*[^}]+\}").unwrap() +}); + +/// Simplify struct representations in type strings. +/// Converts `%{__struct__: Module.Name, field: type(), ...}` to `%Module.Name{}` +fn simplify_structs(s: &str) -> String { + STRUCT_MAP_REGEX.replace_all(s, "%$1{}").to_string() +} + +impl TableFormatter for ModuleGroupResult { + type Entry = UsageInfo; + + fn format_header(&self) -> String { + let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + format!("Functions using \"{}\"", pattern) + } + + fn format_empty_message(&self) -> String { + "No functions found.".to_string() + } + + fn format_summary(&self, total: usize, module_count: usize) -> String { + format!("Found {} function(s) in {} module(s):", total, module_count) + } + + fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { + format!("{}:", module_name) + } + + fn format_entry(&self, usage_info: &UsageInfo, _module: &str, _file: &str) -> String { + format!( + "{}/{} accepts: {} returns: {}", + usage_info.name, + usage_info.arity, + simplify_structs(&usage_info.inputs), + simplify_structs(&usage_info.returns) + ) + } +} + +impl Outputable for StructModulesResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + // Header + lines.push(format!("Modules using \"{}\"", self.struct_pattern)); + lines.push(String::new()); + + if self.modules.is_empty() { + lines.push("No modules found.".to_string()); + return lines.join("\n"); + } + + // Summary + lines.push(format!( + "Found {} module(s) ({} function(s)):", + self.total_modules, self.total_functions + )); + lines.push(String::new()); + + // Table header + lines.push("Module Accepts Returns Total".to_string()); + lines.push("──────────────────────────────────────────────────".to_string()); + + // Table rows + for module in &self.modules { + let line = format!( + "{:<28} {:>7} {:>8} {:>5}", + truncate_module_name(&module.name, 28), + module.accepts_count, + module.returns_count, + module.total + ); + lines.push(line); + } + + lines.join("\n") + } +} + +/// Truncate module name to max width with ellipsis if needed +fn truncate_module_name(name: &str, max_width: usize) -> String { + if name.len() > max_width { + format!("{}…", &name[..max_width - 1]) + } else { + name.to_string() + } +} + +impl Outputable for StructUsageOutput { + fn to_table(&self) -> String { + match self { + StructUsageOutput::Detailed(result) => result.to_table(), + StructUsageOutput::ByModule(result) => result.to_table(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_simplify_structs_basic() { + let input = "%{__struct__: TradeGym.User, name: binary(), age: integer()}"; + let expected = "%TradeGym.User{}"; + assert_eq!(simplify_structs(input), expected); + } + + #[test] + fn test_simplify_structs_with_meta() { + let input = "%{__struct__: TradeGym.Repo.Schemas.User, __meta__: term(), name: binary()}"; + let expected = "%TradeGym.Repo.Schemas.User{}"; + assert_eq!(simplify_structs(input), expected); + } + + #[test] + fn test_simplify_structs_multiple() { + let input = "%{__struct__: Foo.Bar, x: 1} | %{__struct__: Baz.Qux, y: 2}"; + let expected = "%Foo.Bar{} | %Baz.Qux{}"; + assert_eq!(simplify_structs(input), expected); + } + + #[test] + fn test_simplify_structs_no_match() { + let input = "integer() | binary()"; + assert_eq!(simplify_structs(input), input); + } +} diff --git a/cli/src/commands/struct_usage/output_tests.rs b/cli/src/commands/struct_usage/output_tests.rs new file mode 100644 index 0000000..715ae09 --- /dev/null +++ b/cli/src/commands/struct_usage/output_tests.rs @@ -0,0 +1,172 @@ +//! Output formatting tests for struct-usage command. + +#[cfg(test)] +mod tests { + use super::super::execute::{ModuleStructUsage, StructModulesResult, StructUsageOutput, UsageInfo}; + use crate::types::{ModuleGroup, ModuleGroupResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs - Detailed mode + // ========================================================================= + + const EMPTY_DETAILED_TABLE: &str = "\ +Functions using \"User.t\" + +No functions found."; + + const SINGLE_DETAILED_TABLE: &str = "\ +Functions using \"User.t\" + +Found 1 function(s) in 1 module(s): + +MyApp.Accounts: + get_user/1 accepts: integer() returns: %User{}"; + + // ========================================================================= + // Expected outputs - ByModule mode + // ========================================================================= + + const EMPTY_BY_MODULE_TABLE: &str = "\ +Modules using \"User.t\" + +No modules found."; + + const SINGLE_BY_MODULE_TABLE: &str = "\ +Modules using \"User.t\" + +Found 1 module(s) (2 function(s)): + +Module Accepts Returns Total +────────────────────────────────────────────────── +MyApp.Accounts 1 2 2"; + + // ========================================================================= + // Fixtures - Detailed mode + // ========================================================================= + + #[fixture] + fn empty_detailed() -> StructUsageOutput { + StructUsageOutput::Detailed(ModuleGroupResult { + module_pattern: "*".to_string(), + function_pattern: Some("User.t".to_string()), + total_items: 0, + items: vec![], + }) + } + + #[fixture] + fn single_detailed() -> StructUsageOutput { + StructUsageOutput::Detailed(ModuleGroupResult { + module_pattern: "*".to_string(), + function_pattern: Some("User.t".to_string()), + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + function_count: Some(1), + entries: vec![UsageInfo { + name: "get_user".to_string(), + arity: 1, + inputs: "integer()".to_string(), + returns: "%{__struct__: User, id: integer()}".to_string(), + line: 10, + }], + }], + }) + } + + // ========================================================================= + // Fixtures - ByModule mode + // ========================================================================= + + #[fixture] + fn empty_by_module() -> StructUsageOutput { + StructUsageOutput::ByModule(StructModulesResult { + struct_pattern: "User.t".to_string(), + total_modules: 0, + total_functions: 0, + modules: vec![], + }) + } + + #[fixture] + fn single_by_module() -> StructUsageOutput { + StructUsageOutput::ByModule(StructModulesResult { + struct_pattern: "User.t".to_string(), + total_modules: 1, + total_functions: 2, + modules: vec![ModuleStructUsage { + name: "MyApp.Accounts".to_string(), + accepts_count: 1, + returns_count: 2, + total: 2, + }], + }) + } + + // ========================================================================= + // Tests - Detailed mode + // ========================================================================= + + crate::output_table_test! { + test_name: test_detailed_empty, + fixture: empty_detailed, + fixture_type: StructUsageOutput, + expected: EMPTY_DETAILED_TABLE, + } + + crate::output_table_test! { + test_name: test_detailed_single, + fixture: single_detailed, + fixture_type: StructUsageOutput, + expected: SINGLE_DETAILED_TABLE, + } + + // ========================================================================= + // Tests - ByModule mode + // ========================================================================= + + crate::output_table_test! { + test_name: test_by_module_empty, + fixture: empty_by_module, + fixture_type: StructUsageOutput, + expected: EMPTY_BY_MODULE_TABLE, + } + + crate::output_table_test! { + test_name: test_by_module_single, + fixture: single_by_module, + fixture_type: StructUsageOutput, + expected: SINGLE_BY_MODULE_TABLE, + } + + // ========================================================================= + // JSON format tests + // ========================================================================= + + #[rstest] + fn test_detailed_json(single_detailed: StructUsageOutput) { + use crate::output::{OutputFormat, Outputable}; + let output = single_detailed.format(OutputFormat::Json); + let parsed: serde_json::Value = + serde_json::from_str(&output).expect("Should produce valid JSON"); + + // Verify structure + assert!(parsed["items"].is_array()); + assert_eq!(parsed["total_items"], 1); + } + + #[rstest] + fn test_by_module_json(single_by_module: StructUsageOutput) { + use crate::output::{OutputFormat, Outputable}; + let output = single_by_module.format(OutputFormat::Json); + let parsed: serde_json::Value = + serde_json::from_str(&output).expect("Should produce valid JSON"); + + // Verify structure + assert!(parsed["modules"].is_array()); + assert_eq!(parsed["total_modules"], 1); + assert_eq!(parsed["total_functions"], 2); + } +} diff --git a/cli/src/commands/trace/cli_tests.rs b/cli/src/commands/trace/cli_tests.rs new file mode 100644 index 0000000..58f74f4 --- /dev/null +++ b/cli/src/commands/trace/cli_tests.rs @@ -0,0 +1,117 @@ +//! CLI parsing tests for trace command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Required argument tests + // ========================================================================= + + crate::cli_required_arg_test! { + command: "trace", + test_name: test_requires_module, + required_arg: "", + } + + crate::cli_required_arg_test! { + command: "trace", + test_name: test_requires_function, + required_arg: "", + } + + // ========================================================================= + // Option tests + // ========================================================================= + + crate::cli_option_test! { + command: "trace", + variant: Trace, + test_name: test_with_module_and_function, + args: ["MyApp.Accounts", "get_user"], + field: module, + expected: "MyApp.Accounts", + } + + crate::cli_option_test! { + command: "trace", + variant: Trace, + test_name: test_function_name, + args: ["MyApp.Accounts", "get_user"], + field: function, + expected: "get_user", + } + + crate::cli_option_test! { + command: "trace", + variant: Trace, + test_name: test_with_project, + args: ["MyApp", "foo", "--project", "my_custom_project"], + field: common.project, + expected: "my_custom_project", + } + + crate::cli_option_test! { + command: "trace", + variant: Trace, + test_name: test_with_depth, + args: ["MyApp", "foo", "--depth", "10"], + field: depth, + expected: 10, + } + + crate::cli_option_test! { + command: "trace", + variant: Trace, + test_name: test_with_limit, + args: ["MyApp", "foo", "--limit", "50"], + field: common.limit, + expected: 50, + } + + // ========================================================================= + // Limit validation tests + // ========================================================================= + + crate::cli_limit_tests! { + command: "trace", + variant: Trace, + required_args: ["MyApp", "foo"], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Edge case tests (depth validation - different from standard limit) + // ========================================================================= + + #[rstest] + fn test_depth_default() { + let args = Args::try_parse_from(["code_search", "trace", "MyApp", "foo"]).unwrap(); + match args.command { + crate::commands::Command::Trace(cmd) => { + assert_eq!(cmd.depth, 5); + } + _ => panic!("Expected Trace command"), + } + } + + #[rstest] + fn test_depth_zero_rejected() { + let result = + Args::try_parse_from(["code_search", "trace", "MyApp", "foo", "--depth", "0"]); + assert!(result.is_err()); + } + + #[rstest] + fn test_depth_exceeds_max_rejected() { + let result = + Args::try_parse_from(["code_search", "trace", "MyApp", "foo", "--depth", "21"]); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/trace/execute.rs b/cli/src/commands/trace/execute.rs new file mode 100644 index 0000000..7d560bb --- /dev/null +++ b/cli/src/commands/trace/execute.rs @@ -0,0 +1,179 @@ +use std::collections::HashMap; +use std::error::Error; + +use super::TraceCmd; +use crate::commands::Execute; +use crate::queries::trace::trace_calls; +use crate::types::{Call, TraceDirection, TraceEntry, TraceResult}; + +impl TraceResult { + /// Build a flattened trace from Call objects + pub fn from_calls( + start_module: String, + start_function: String, + max_depth: u32, + calls: Vec, + ) -> Self { + let mut entries = Vec::new(); + let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); + + // Add the starting function as the root entry at depth 0 + entries.push(TraceEntry { + module: start_module.clone(), + function: start_function.clone(), + arity: 0, // Will be updated from first call if available + kind: String::new(), + start_line: 0, + end_line: 0, + file: String::new(), + depth: 0, + line: 0, + parent_index: None, + }); + entry_index_map.insert((start_module.clone(), start_function.clone(), 0, 0), 0); + + if calls.is_empty() { + return Self::empty(start_module, start_function, max_depth, TraceDirection::Forward); + } + + // Group calls by depth, consuming the Vec to take ownership + let mut by_depth: HashMap> = HashMap::new(); + for call in calls { + if let Some(depth) = call.depth { + by_depth.entry(depth).or_default().push(call); + } + } + + // Process depth 1 (direct callees from start function) + if let Some(depth1_calls) = by_depth.remove(&1) { + // Track seen entries by index into entries vec (avoids storing strings) + let mut seen_at_depth: std::collections::HashSet = std::collections::HashSet::new(); + + for call in depth1_calls { + // Check if we already have this callee at this depth + let existing = entries.iter().position(|e| { + e.depth == 1 + && e.module == call.callee.module.as_ref() + && e.function == call.callee.name.as_ref() + && e.arity == call.callee.arity + }); + + if existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX)) { + if existing.is_none() { + let entry_idx = entries.len(); + // Convert from Rc to String for storage + let module = call.callee.module.to_string(); + let function = call.callee.name.to_string(); + let arity = call.callee.arity; + entry_index_map.insert((module.clone(), function.clone(), arity, 1i64), entry_idx); + entries.push(TraceEntry { + module, + function, + arity, + kind: call.callee.kind.as_deref().unwrap_or("").to_string(), + start_line: call.callee.start_line.unwrap_or(0), + end_line: call.callee.end_line.unwrap_or(0), + file: call.callee.file.as_deref().unwrap_or("").to_string(), + depth: 1, + line: call.line, + parent_index: Some(0), + }); + } + } + } + } + + // Process deeper levels + for depth in 2..=max_depth as i64 { + if let Some(depth_calls) = by_depth.remove(&depth) { + for call in depth_calls { + // Check if we already have this callee at this depth + let existing = entries.iter().position(|e| { + e.depth == depth + && e.module == call.callee.module.as_ref() + && e.function == call.callee.name.as_ref() + && e.arity == call.callee.arity + }); + + if existing.is_none() { + // Find parent index using references (no cloning) + let parent_index = entries.iter().position(|e| { + e.depth == depth - 1 + && e.module == call.caller.module.as_ref() + && e.function == call.caller.name.as_ref() + && e.arity == call.caller.arity + }); + + if parent_index.is_some() { + let entry_idx = entries.len(); + // Convert from Rc to String for storage + let module = call.callee.module.to_string(); + let function = call.callee.name.to_string(); + let arity = call.callee.arity; + entry_index_map.insert((module.clone(), function.clone(), arity, depth), entry_idx); + entries.push(TraceEntry { + module, + function, + arity, + kind: call.callee.kind.as_deref().unwrap_or("").to_string(), + start_line: call.callee.start_line.unwrap_or(0), + end_line: call.callee.end_line.unwrap_or(0), + file: call.callee.file.as_deref().unwrap_or("").to_string(), + depth, + line: call.line, + parent_index, + }); + } + } + } + } + } + + let total_items = entries.len() - 1; // Exclude the root entry from count + + Self { + module: start_module, + function: start_function, + max_depth, + direction: TraceDirection::Forward, + total_items, + entries, + } + } +} + +impl Execute for TraceCmd { + type Output = TraceResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let calls = trace_calls( + db, + &self.module, + &self.function, + self.arity, + &self.common.project, + self.common.regex, + self.depth, + self.common.limit, + )?; + + Ok(TraceResult::from_calls( + self.module, + self.function, + self.depth, + calls, + )) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_empty_trace() { + let result = TraceResult::from_calls("TestModule".to_string(), "test_func".to_string(), 5, vec![]); + assert_eq!(result.total_items, 0); + assert_eq!(result.entries.len(), 0); + } +} diff --git a/cli/src/commands/trace/execute_tests.rs b/cli/src/commands/trace/execute_tests.rs new file mode 100644 index 0000000..ee7e69a --- /dev/null +++ b/cli/src/commands/trace/execute_tests.rs @@ -0,0 +1,124 @@ +//! Execute tests for trace command. + +#[cfg(test)] +mod tests { + use super::super::TraceCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // Controller.index only calls Accounts.list_users at depth 1 + crate::execute_test! { + test_name: test_trace_single_depth, + fixture: populated_db, + cmd: TraceCmd { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: None, + depth: 1, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 1); + assert_eq!(result.entries.len(), 2); // Root + 1 callee + // Entry at index 0 is the root (Controller.index) + assert_eq!(result.entries[0].module, "MyApp.Controller"); + // Entry at index 1 is the callee (Accounts.list_users) + assert_eq!(result.entries[1].module, "MyApp.Accounts"); + assert_eq!(result.entries[1].function, "list_users"); + }, + } + + // Controller.index -> list_users -> all (2 steps with depth 2) + crate::execute_test! { + test_name: test_trace_multiple_depths, + fixture: populated_db, + cmd: TraceCmd { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: None, + depth: 3, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2); + }, + } + + crate::execute_test! { + test_name: test_trace_with_depth_limit, + fixture: populated_db, + cmd: TraceCmd { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: None, + depth: 2, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2); + assert!(result.max_depth <= 2); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_trace_no_match, + fixture: populated_db, + cmd: TraceCmd { + module: "NonExistent".to_string(), + function: "foo".to_string(), + arity: None, + depth: 5, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: entries, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: TraceCmd, + cmd: TraceCmd { + module: "MyApp".to_string(), + function: "foo".to_string(), + arity: None, + depth: 5, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/trace/mod.rs b/cli/src/commands/trace/mod.rs new file mode 100644 index 0000000..06faf02 --- /dev/null +++ b/cli/src/commands/trace/mod.rs @@ -0,0 +1,47 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Trace call chains from a starting function (forward traversal) +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search trace MyApp.Web index # Trace from controller action + code_search trace MyApp handle_call --depth 10 # Deeper traversal + code_search trace -r 'MyApp\\..*' 'handle_.*' # Regex pattern +")] +pub struct TraceCmd { + /// Starting module name (exact match or pattern with --regex) + pub module: String, + + /// Starting function name (exact match or pattern with --regex) + pub function: String, + + /// Function arity (optional) + #[arg(short, long)] + pub arity: Option, + + /// Maximum depth to traverse (1-20) + #[arg(long, default_value_t = 5, value_parser = clap::value_parser!(u32).range(1..=20))] + pub depth: u32, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for TraceCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/trace/output.rs b/cli/src/commands/trace/output.rs new file mode 100644 index 0000000..a09379d --- /dev/null +++ b/cli/src/commands/trace/output.rs @@ -0,0 +1,179 @@ +//! Output formatting for trace and reverse-trace command results. + +use crate::output::Outputable; +use crate::types::{TraceResult, TraceDirection}; + +impl Outputable for TraceResult { + fn to_table(&self) -> String { + match self.direction { + TraceDirection::Forward => format_trace(self), + TraceDirection::Backward => format_reverse_trace(self), + } + } +} + +/// Format a forward trace +fn format_trace(result: &TraceResult) -> String { + let mut lines = Vec::new(); + + let header = format!("Trace from: {}.{}", result.module, result.function); + lines.push(header); + lines.push(format!("Max depth: {}", result.max_depth)); + lines.push(String::new()); + + if result.entries.is_empty() { + lines.push("No calls found.".to_string()); + return lines.join("\n"); + } + + lines.push(format!("Found {} call(s) in chain:", result.total_items)); + lines.push(String::new()); + + // Find root entries (those with no parent) + for (idx, entry) in result.entries.iter().enumerate() { + if entry.parent_index.is_none() { + format_entry(&mut lines, &result.entries, idx, 0); + } + } + + lines.join("\n") +} + +/// Format a reverse trace +fn format_reverse_trace(result: &TraceResult) -> String { + let mut lines = Vec::new(); + + let header = format!("Reverse trace to: {}.{}", result.module, result.function); + lines.push(header); + lines.push(format!("Max depth: {}", result.max_depth)); + lines.push(String::new()); + + if result.entries.is_empty() { + lines.push("No callers found.".to_string()); + return lines.join("\n"); + } + + lines.push(format!("Found {} caller(s) in chain:", result.total_items)); + lines.push(String::new()); + + // Find root entries (those with no parent) + for (idx, entry) in result.entries.iter().enumerate() { + if entry.parent_index.is_none() { + format_reverse_entry(&mut lines, &result.entries, idx, 0); + } + } + + lines.join("\n") +} + +/// Format a reverse trace entry (callers going up the chain) +fn format_reverse_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { + let entry = &entries[idx]; + let indent = " ".repeat(depth); + let kind_str = if entry.kind.is_empty() { + String::new() + } else { + format!(" [{}]", entry.kind) + }; + + // Extract just the filename from path + let filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); + + // For root entries (no parent), show without prefix + if entry.parent_index.is_none() { + lines.push(format!( + "{}{}.{}/{}{} ({}:L{}:{})", + indent, entry.module, entry.function, entry.arity, kind_str, + filename, entry.start_line, entry.end_line + )); + } else { + // For child entries, show with arrow indicating "called by" relationship + lines.push(format!( + "{}← @ L{} {}.{}/{}{} ({}:L{}:{})", + indent, entry.line, entry.module, entry.function, entry.arity, kind_str, + filename, entry.start_line, entry.end_line + )); + } + + // Find children (additional callers going up the chain) + for (child_idx, child) in entries.iter().enumerate() { + if child.parent_index == Some(idx) { + format_reverse_entry(lines, entries, child_idx, depth + 1); + } + } +} + +/// Recursively format an entry and its children +fn format_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { + let entry = &entries[idx]; + let indent = " ".repeat(depth); + let kind_str = if entry.kind.is_empty() { + String::new() + } else { + format!(" [{}]", entry.kind) + }; + + // Extract just the filename from path + let filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); + + lines.push(format!( + "{}{}.{}/{}{} ({}:L{}:{})", + indent, entry.module, entry.function, entry.arity, kind_str, + filename, entry.start_line, entry.end_line + )); + + // Find children of this entry + for (child_idx, child) in entries.iter().enumerate() { + if child.parent_index == Some(idx) { + format_call(lines, entries, child_idx, depth + 1, &entry.module, &entry.file); + } + } +} + +/// Format a child call/caller entry +fn format_call( + lines: &mut Vec, + entries: &[crate::types::TraceEntry], + idx: usize, + depth: usize, + parent_module: &str, + parent_file: &str, +) { + let entry = &entries[idx]; + let indent = " ".repeat(depth); + + // Show module only if different from parent + let name = if entry.module == parent_module { + format!("{}/{}", entry.function, entry.arity) + } else { + format!("{}.{}/{}", entry.module, entry.function, entry.arity) + }; + + let kind_str = if entry.kind.is_empty() { + String::new() + } else { + format!(" [{}]", entry.kind) + }; + + // Extract just the filename + let child_filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); + let parent_filename = parent_file.rsplit('/').next().unwrap_or(parent_file); + + let location = if child_filename == parent_filename { + format!("L{}:{}", entry.start_line, entry.end_line) + } else { + format!("{}:L{}:{}", child_filename, entry.start_line, entry.end_line) + }; + + lines.push(format!( + "{}→ @ L{} {}{} ({})", + indent, entry.line, name, kind_str, location + )); + + // Recurse into children of this entry + for (child_idx, child) in entries.iter().enumerate() { + if child.parent_index == Some(idx) { + format_call(lines, entries, child_idx, depth + 1, &entry.module, &entry.file); + } + } +} diff --git a/cli/src/commands/trace/output_tests.rs b/cli/src/commands/trace/output_tests.rs new file mode 100644 index 0000000..d26d11c --- /dev/null +++ b/cli/src/commands/trace/output_tests.rs @@ -0,0 +1,165 @@ +//! Output formatting tests for trace command. + +#[cfg(test)] +mod tests { + use crate::types::{TraceDirection, TraceEntry, TraceResult}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Trace from: MyApp.Controller.index +Max depth: 5 + +No calls found."; + + const SINGLE_TABLE: &str = "\ +Trace from: MyApp.Controller.index +Max depth: 5 + +Found 1 call(s) in chain: + +MyApp.Controller.index/1 [def] (controller.ex:L5:12) + → @ L7 MyApp.Service.fetch/1 [def] (service.ex:L10:20)"; + + const MULTI_DEPTH_TABLE: &str = "\ +Trace from: MyApp.Controller.index +Max depth: 5 + +Found 2 call(s) in chain: + +MyApp.Controller.index/1 [def] (controller.ex:L5:12) + → @ L7 MyApp.Service.fetch/1 [def] (service.ex:L10:20) + → @ L15 MyApp.Repo.get/2 (repo.ex:L30:40)"; + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> TraceResult { + TraceResult { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + max_depth: 5, + direction: TraceDirection::Forward, + total_items: 0, + entries: vec![], + } + } + + #[fixture] + fn single_depth_result() -> TraceResult { + TraceResult { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + max_depth: 5, + direction: TraceDirection::Forward, + total_items: 1, + entries: vec![ + // Root entry: the starting function + TraceEntry { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 5, + end_line: 12, + file: "/path/to/controller.ex".to_string(), + depth: 0, + line: 0, + parent_index: None, + }, + // Callee at depth 1 + TraceEntry { + module: "MyApp.Service".to_string(), + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "/path/to/service.ex".to_string(), + depth: 1, + line: 7, + parent_index: Some(0), + }, + ], + } + } + + #[fixture] + fn multi_depth_result() -> TraceResult { + TraceResult { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + max_depth: 5, + direction: TraceDirection::Forward, + total_items: 2, + entries: vec![ + TraceEntry { + module: "MyApp.Controller".to_string(), + function: "index".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 5, + end_line: 12, + file: "/path/to/controller.ex".to_string(), + depth: 0, + line: 0, + parent_index: None, + }, + TraceEntry { + module: "MyApp.Service".to_string(), + function: "fetch".to_string(), + arity: 1, + kind: "def".to_string(), + start_line: 10, + end_line: 20, + file: "/path/to/service.ex".to_string(), + depth: 1, + line: 7, + parent_index: Some(0), + }, + TraceEntry { + module: "MyApp.Repo".to_string(), + function: "get".to_string(), + arity: 2, + kind: String::new(), + start_line: 30, + end_line: 40, + file: "repo.ex".to_string(), + depth: 2, + line: 15, + parent_index: Some(1), + }, + ], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + #[rstest] + fn test_empty_trace(empty_result: TraceResult) { + use crate::output::Outputable; + let output = empty_result.to_table(); + assert_eq!(output, EMPTY_TABLE); + } + + #[rstest] + fn test_single_depth_trace(single_depth_result: TraceResult) { + use crate::output::Outputable; + let output = single_depth_result.to_table(); + assert_eq!(output, SINGLE_TABLE); + } + + #[rstest] + fn test_multi_depth_trace(multi_depth_result: TraceResult) { + use crate::output::Outputable; + let output = multi_depth_result.to_table(); + assert_eq!(output, MULTI_DEPTH_TABLE); + } +} diff --git a/cli/src/commands/unused/cli_tests.rs b/cli/src/commands/unused/cli_tests.rs new file mode 100644 index 0000000..26c1ecd --- /dev/null +++ b/cli/src/commands/unused/cli_tests.rs @@ -0,0 +1,135 @@ +//! CLI parsing tests for unused command using the test DSL. + +#[cfg(test)] +mod tests { + use crate::cli::Args; + use clap::Parser; + use rstest::rstest; + + // ========================================================================= + // Macro-generated tests (standard patterns) + // ========================================================================= + + // Unused has no required args, so test defaults + crate::cli_defaults_test! { + command: "unused", + variant: Unused, + required_args: [], + defaults: { + common.project: "default", + common.regex: false, + private_only: false, + public_only: false, + exclude_generated: false, + common.limit: 100, + }, + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_module, + args: ["MyApp"], + field: module, + expected: Some("MyApp".to_string()), + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_project, + args: ["--project", "my_app"], + field: common.project, + expected: "my_app", + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_regex, + args: ["MyApp\\..*", "--regex"], + field: common.regex, + expected: true, + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_limit, + args: ["--limit", "50"], + field: common.limit, + expected: 50, + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_private_only, + args: ["--private-only"], + field: private_only, + expected: true, + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_public_only, + args: ["--public-only"], + field: public_only, + expected: true, + } + + crate::cli_option_test! { + command: "unused", + variant: Unused, + test_name: test_with_exclude_generated, + args: ["--exclude-generated"], + field: exclude_generated, + expected: true, + } + + crate::cli_limit_tests! { + command: "unused", + variant: Unused, + required_args: [], + limit: { + field: common.limit, + default: 100, + max: 1000, + }, + } + + // ========================================================================= + // Edge case tests (short flags, conflicts) + // ========================================================================= + + #[rstest] + fn test_with_short_flags() { + let args = Args::try_parse_from(["code_search", "unused", "-p", "-x"]).unwrap(); + match args.command { + crate::commands::Command::Unused(cmd) => { + assert!(cmd.private_only); + assert!(cmd.exclude_generated); + } + _ => panic!("Expected Unused command"), + } + } + + #[rstest] + fn test_public_only_short() { + let args = Args::try_parse_from(["code_search", "unused", "-P"]).unwrap(); + match args.command { + crate::commands::Command::Unused(cmd) => { + assert!(cmd.public_only); + } + _ => panic!("Expected Unused command"), + } + } + + #[rstest] + fn test_private_and_public_conflict() { + let result = + Args::try_parse_from(["code_search", "unused", "--private-only", "--public-only"]); + assert!(result.is_err()); + } +} diff --git a/cli/src/commands/unused/execute.rs b/cli/src/commands/unused/execute.rs new file mode 100644 index 0000000..77e86b2 --- /dev/null +++ b/cli/src/commands/unused/execute.rs @@ -0,0 +1,70 @@ +use std::error::Error; + +use serde::Serialize; + +use super::UnusedCmd; +use crate::commands::Execute; +use crate::queries::unused::{find_unused_functions, UnusedFunction}; +use crate::types::ModuleCollectionResult; + +/// An unused function within a module +#[derive(Debug, Clone, Serialize)] +pub struct UnusedFunc { + pub name: String, + pub arity: i64, + pub kind: String, + pub line: i64, +} + +impl ModuleCollectionResult { + /// Build grouped result from flat UnusedFunction list + fn from_functions( + module_pattern: String, + functions: Vec, + ) -> Self { + let total_items = functions.len(); + + // Use helper to group by module, tracking file for each module + let items = crate::utils::group_by_module_with_file(functions, |func| { + let unused_func = UnusedFunc { + name: func.name, + arity: func.arity, + kind: func.kind, + line: func.line, + }; + (func.module, unused_func, func.file) + }); + + ModuleCollectionResult { + module_pattern, + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items, + items, + } + } +} + +impl Execute for UnusedCmd { + type Output = ModuleCollectionResult; + + fn execute(self, db: &cozo::DbInstance) -> Result> { + let functions = find_unused_functions( + db, + self.module.as_deref(), + &self.common.project, + self.common.regex, + self.private_only, + self.public_only, + self.exclude_generated, + self.common.limit, + )?; + + Ok(>::from_functions( + self.module.unwrap_or_else(|| "*".to_string()), + functions, + )) + } +} + diff --git a/cli/src/commands/unused/execute_tests.rs b/cli/src/commands/unused/execute_tests.rs new file mode 100644 index 0000000..6a04534 --- /dev/null +++ b/cli/src/commands/unused/execute_tests.rs @@ -0,0 +1,195 @@ +//! Execute tests for unused command. + +#[cfg(test)] +mod tests { + use super::super::UnusedCmd; + use crate::commands::CommonArgs; + use rstest::{fixture, rstest}; + + crate::shared_fixture! { + fixture_name: populated_db, + fixture_type: call_graph, + project: "test_project", + } + + // ========================================================================= + // Core functionality tests + // ========================================================================= + + // Uncalled functions: index, show, create (Controller), get_user/2 + validate_email (Accounts), insert (Repo) = 6 + // Note: get_user/1 is called but get_user/2 is not (Controller.show calls arity 1 only) + crate::execute_test! { + test_name: test_unused_finds_uncalled_functions, + fixture: populated_db, + cmd: UnusedCmd { + module: None, + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 6); + let all_funcs: Vec<&str> = result.items.iter() + .flat_map(|m| m.entries.iter().map(|f| f.name.as_str())) + .collect(); + assert!(all_funcs.contains(&"validate_email")); + assert!(all_funcs.contains(&"insert")); + }, + } + + // In Accounts: validate_email (defp) and get_user/2 (def, not called) = 2 + crate::execute_test! { + test_name: test_unused_with_module_filter, + fixture: populated_db, + cmd: UnusedCmd { + module: Some("Accounts".to_string()), + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 2); + }, + } + + // Controller has 3 uncalled functions + crate::execute_test! { + test_name: test_unused_with_regex_filter, + fixture: populated_db, + cmd: UnusedCmd { + module: Some("^MyApp\\.Controller$".to_string()), + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: true, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 3); + }, + } + + // ========================================================================= + // No match / empty result tests + // ========================================================================= + + crate::execute_no_match_test! { + test_name: test_unused_no_match, + fixture: populated_db, + cmd: UnusedCmd { + module: Some("NonExistent".to_string()), + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + empty_field: items, + } + + // ========================================================================= + // Filter tests + // ========================================================================= + + crate::execute_test! { + test_name: test_unused_with_limit, + fixture: populated_db, + cmd: UnusedCmd { + module: None, + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 1, + }, + }, + assertions: |result| { + // Limit applies to raw results before grouping + assert_eq!(result.total_items, 1); + }, + } + + // validate_email is the only private (defp) uncalled function + crate::execute_test! { + test_name: test_unused_private_only, + fixture: populated_db, + cmd: UnusedCmd { + module: None, + private_only: true, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 1); + assert_eq!(result.items[0].entries[0].name, "validate_email"); + assert_eq!(result.items[0].entries[0].kind, "defp"); + }, + } + + // 5 public uncalled: index, show, create (Controller), get_user/2 (Accounts), insert (Repo) + crate::execute_test! { + test_name: test_unused_public_only, + fixture: populated_db, + cmd: UnusedCmd { + module: None, + private_only: false, + public_only: true, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + assertions: |result| { + assert_eq!(result.total_items, 5); + for module in &result.items { + for func in &module.entries { + assert_eq!(func.kind, "def"); + } + } + }, + } + + // ========================================================================= + // Error handling tests + // ========================================================================= + + crate::execute_empty_db_test! { + cmd_type: UnusedCmd, + cmd: UnusedCmd { + module: None, + private_only: false, + public_only: false, + exclude_generated: false, + common: CommonArgs { + project: "test_project".to_string(), + regex: false, + limit: 100, + }, + }, + } +} diff --git a/cli/src/commands/unused/mod.rs b/cli/src/commands/unused/mod.rs new file mode 100644 index 0000000..2304e99 --- /dev/null +++ b/cli/src/commands/unused/mod.rs @@ -0,0 +1,50 @@ +mod cli_tests; +mod execute; +mod execute_tests; +mod output; +mod output_tests; + +use std::error::Error; + +use clap::Args; +use cozo::DbInstance; + +use crate::commands::{CommandRunner, CommonArgs, Execute}; +use crate::output::{OutputFormat, Outputable}; + +/// Find functions that are never called +#[derive(Args, Debug)] +#[command(after_help = "\ +Examples: + code_search unused # Find all unused functions + code_search unused MyApp.Accounts # Filter to specific module + code_search unused -P # Unused public functions (entry points) + code_search unused -p # Unused private functions (dead code) + code_search unused -Px # Public only, exclude generated + code_search unused 'Accounts.*' -r # Match module with regex")] +pub struct UnusedCmd { + /// Module pattern to filter results (substring match by default, regex with -r) + pub module: Option, + + /// Only show private functions (defp, defmacrop) - likely dead code + #[arg(short, long, default_value_t = false, conflicts_with = "public_only")] + pub private_only: bool, + + /// Only show public functions (def, defmacro) - potential entry points + #[arg(short = 'P', long, default_value_t = false, conflicts_with = "private_only")] + pub public_only: bool, + + /// Exclude compiler-generated functions (__struct__, __info__, etc.) + #[arg(short = 'x', long, default_value_t = false)] + pub exclude_generated: bool, + + #[command(flatten)] + pub common: CommonArgs, +} + +impl CommandRunner for UnusedCmd { + fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { + let result = self.execute(db)?; + Ok(result.format(format)) + } +} diff --git a/cli/src/commands/unused/output.rs b/cli/src/commands/unused/output.rs new file mode 100644 index 0000000..2ca5e6b --- /dev/null +++ b/cli/src/commands/unused/output.rs @@ -0,0 +1,43 @@ +//! Output formatting for unused command results. + +use crate::output::Outputable; +use crate::types::ModuleCollectionResult; +use super::execute::UnusedFunc; + +impl Outputable for ModuleCollectionResult { + fn to_table(&self) -> String { + let mut lines = Vec::new(); + + let filter_info = if self.module_pattern != "*" { + format!(" (module: {})", self.module_pattern) + } else { + String::new() + }; + + lines.push(format!("Unused functions{}", filter_info)); + lines.push(String::new()); + + if !self.items.is_empty() { + lines.push(format!( + "Found {} unused function(s) in {} module(s):", + self.total_items, + self.items.len() + )); + lines.push(String::new()); + + for module in &self.items { + lines.push(format!("{} ({}):", module.name, module.file)); + for func in &module.entries { + lines.push(format!( + " {}/{} [{}] L{}", + func.name, func.arity, func.kind, func.line + )); + } + } + } else { + lines.push("No unused functions found.".to_string()); + } + + lines.join("\n") + } +} diff --git a/cli/src/commands/unused/output_tests.rs b/cli/src/commands/unused/output_tests.rs new file mode 100644 index 0000000..096bb96 --- /dev/null +++ b/cli/src/commands/unused/output_tests.rs @@ -0,0 +1,143 @@ +//! Output formatting tests for unused command. + +#[cfg(test)] +mod tests { + use super::super::execute::UnusedFunc; + use crate::types::{ModuleCollectionResult, ModuleGroup}; + use rstest::{fixture, rstest}; + + // ========================================================================= + // Expected outputs + // ========================================================================= + + const EMPTY_TABLE: &str = "\ +Unused functions + +No unused functions found."; + + const SINGLE_TABLE: &str = "\ +Unused functions + +Found 1 unused function(s) in 1 module(s): + +MyApp.Accounts (lib/accounts.ex): + unused_helper/0 [defp] L35"; + + const FILTERED_TABLE: &str = "\ +Unused functions (module: Accounts) + +Found 1 unused function(s) in 1 module(s): + +MyApp.Accounts (lib/accounts.ex): + unused_helper/0 [defp] L35"; + + + // ========================================================================= + // Fixtures + // ========================================================================= + + #[fixture] + fn empty_result() -> ModuleCollectionResult { + ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 0, + items: vec![], + } + } + + #[fixture] + fn single_result() -> ModuleCollectionResult { + ModuleCollectionResult { + module_pattern: "*".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + entries: vec![UnusedFunc { + name: "unused_helper".to_string(), + arity: 0, + kind: "defp".to_string(), + line: 35, + }], + function_count: None, + }], + } + } + + #[fixture] + fn filtered_result() -> ModuleCollectionResult { + ModuleCollectionResult { + module_pattern: "Accounts".to_string(), + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/accounts.ex".to_string(), + entries: vec![UnusedFunc { + name: "unused_helper".to_string(), + arity: 0, + kind: "defp".to_string(), + line: 35, + }], + function_count: None, + }], + } + } + + // ========================================================================= + // Tests + // ========================================================================= + + crate::output_table_test! { + test_name: test_to_table_empty, + fixture: empty_result, + fixture_type: ModuleCollectionResult, + expected: EMPTY_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_single, + fixture: single_result, + fixture_type: ModuleCollectionResult, + expected: SINGLE_TABLE, + } + + crate::output_table_test! { + test_name: test_to_table_filtered, + fixture: filtered_result, + fixture_type: ModuleCollectionResult, + expected: FILTERED_TABLE, + } + + crate::output_table_test! { + test_name: test_format_json, + fixture: single_result, + fixture_type: ModuleCollectionResult, + expected: crate::test_utils::load_output_fixture("unused", "single.json"), + format: Json, + } + + crate::output_table_test! { + test_name: test_format_toon, + fixture: single_result, + fixture_type: ModuleCollectionResult, + expected: crate::test_utils::load_output_fixture("unused", "single.toon"), + format: Toon, + } + + crate::output_table_test! { + test_name: test_format_toon_empty, + fixture: empty_result, + fixture_type: ModuleCollectionResult, + expected: crate::test_utils::load_output_fixture("unused", "empty.toon"), + format: Toon, + } +} diff --git a/cli/src/dedup.rs b/cli/src/dedup.rs new file mode 100644 index 0000000..6fd3e55 --- /dev/null +++ b/cli/src/dedup.rs @@ -0,0 +1,112 @@ +//! Deduplication utilities for reducing code duplication across commands. +//! +//! This module provides reusable patterns for deduplicating collections using different strategies: +//! - Strategy A: HashSet retain pattern (deduplicate_retain) - for in-place deduplication after sorting +//! - Strategy B: HashSet prevention pattern (DeduplicationFilter) - for preventing duplicates during collection + +use std::collections::HashSet; +use std::hash::Hash; + +/// Strategy A: HashSet retain pattern - deduplicate in-place +/// +/// Use this when you have a collection that's already been sorted, and you want to remove +/// duplicate entries while preserving the sort order. +/// +/// # Arguments +/// * `items` - Mutable vector of items to deduplicate +/// * `key_fn` - Function that extracts the deduplication key from each item +/// +/// # Example +/// ```ignore +/// let mut calls = vec![...]; +/// calls.sort_by_key(|c| c.line); +/// deduplicate_retain(&mut calls, |c| { +/// (c.callee.module.clone(), c.callee.name.clone(), c.callee.arity) +/// }); +/// ``` +pub fn deduplicate_retain(items: &mut Vec, key_fn: F) +where + F: Fn(&T) -> K, + K: Eq + Hash, +{ + let mut seen: HashSet = HashSet::new(); + items.retain(|item| seen.insert(key_fn(item))); +} + +/// Combined sort and deduplicate operation. +/// +/// Sorts a collection using a comparator, then deduplicates using a different key. +/// Preserves the first occurrence of each duplicate. +/// +/// Use this when you need to: +/// 1. Sort items by one criteria (e.g., line number) +/// 2. Remove duplicates based on different criteria (e.g., callee name) +/// +/// # Arguments +/// * `items` - Mutable vector of items to sort and deduplicate +/// * `sort_cmp` - Comparator function that returns the ordering between two items +/// * `dedup_key_fn` - Function that extracts the deduplication key +/// +/// # Example +/// ```ignore +/// let mut calls = vec![...]; +/// sort_and_deduplicate( +/// &mut calls, +/// |a, b| a.line.cmp(&b.line), // Sort by line number - no allocation +/// |c| (c.callee.module.clone(), c.callee.name.clone(), c.callee.arity) // Dedup by callee +/// ); +/// ``` +pub fn sort_and_deduplicate( + items: &mut Vec, + sort_cmp: SC, + dedup_key: DK, +) +where + SC: FnMut(&T, &T) -> std::cmp::Ordering, + DK: Fn(&T) -> D, + D: Eq + Hash, +{ + items.sort_by(sort_cmp); + deduplicate_retain(items, dedup_key); +} + +/// Strategy B: HashSet prevention pattern - check before adding +/// +/// Use this when collecting items and you want to prevent duplicates from being added +/// in the first place, without needing to sort or post-process. +/// +/// # Example +/// ```ignore +/// let mut filter = DeduplicationFilter::new(); +/// for entry in entries { +/// if filter.should_process(entry_key) { +/// // Add entry to result +/// } +/// } +/// ``` +#[derive(Debug)] +pub struct DeduplicationFilter { + processed: HashSet, +} + +impl DeduplicationFilter { + /// Create a new empty deduplication filter + pub fn new() -> Self { + Self { + processed: HashSet::new(), + } + } + + /// Check if a key should be processed (inserted into the set) + /// + /// Returns true if the key is new and was successfully inserted, false if it was already present. + pub fn should_process(&mut self, key: K) -> bool { + self.processed.insert(key) + } +} + +impl Default for DeduplicationFilter { + fn default() -> Self { + Self::new() + } +} diff --git a/cli/src/main.rs b/cli/src/main.rs index 6b83fa5..63a857c 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,33 @@ -// CLI crate entry point -// Modules will be migrated here in subsequent refactoring tickets -fn main() { - println!("Code search CLI - workspace refactoring in progress"); +use clap::Parser; + +mod cli; +mod commands; +mod db; +mod dedup; +pub mod output; +mod queries; +pub mod types; +mod utils; +#[macro_use] +mod test_macros; +#[cfg(test)] +pub mod fixtures; +#[cfg(test)] +pub mod test_utils; +use cli::Args; +use commands::CommandRunner; + +fn main() -> Result<(), Box> { + let args = Args::parse(); + let db_path = cli::resolve_db_path(args.db); + + // Create .code_search directory if using default path + if db_path == std::path::PathBuf::from(".code_search/cozo.sqlite") { + std::fs::create_dir_all(".code_search").ok(); + } + + let db = db::open_db(&db_path)?; + let output = args.command.run(&db, args.format)?; + println!("{}", output); + Ok(()) } diff --git a/cli/src/output.rs b/cli/src/output.rs new file mode 100644 index 0000000..c52beb6 --- /dev/null +++ b/cli/src/output.rs @@ -0,0 +1,186 @@ +//! Output formatting for command results. +//! +//! Supports multiple output formats: table (human-readable), JSON, and toon. + +use clap::ValueEnum; +use serde::Serialize; +use crate::types::{ModuleGroupResult, ModuleCollectionResult}; + +/// Output format for command results +#[derive(Debug, Clone, Copy, Default, ValueEnum)] +pub enum OutputFormat { + /// Human-readable table format + #[default] + Table, + /// JSON format + Json, + /// Token-efficient toon format + Toon, +} + +/// Trait for types that can be formatted for output +pub trait Outputable: Serialize { + /// Format as a human-readable table + fn to_table(&self) -> String; + + /// Format according to the specified output format + fn format(&self, format: OutputFormat) -> String { + match format { + OutputFormat::Table => self.to_table(), + OutputFormat::Json => serde_json::to_string_pretty(self).unwrap_or_default(), + OutputFormat::Toon => { + let json_value = serde_json::to_value(self).unwrap_or_default(); + toon::encode(&json_value, None) + } + } + } +} + +/// Trait for customizing table formatting for module-grouped results +/// +/// Provides hooks for formatting headers, empty states, summaries, and individual entries. +/// Used as a foundation for generating default `to_table()` implementations for generic +/// result types like `ModuleGroupResult` and `ModuleCollectionResult`. +pub trait TableFormatter { + type Entry; + + /// Format the header line(s) of the table + fn format_header(&self) -> String; + + /// Format the message shown when there are no results + fn format_empty_message(&self) -> String; + + /// Format the summary line after header and before entries + /// + /// # Arguments + /// * `total` - Total number of entries across all modules + /// * `module_count` - Number of modules in the result + fn format_summary(&self, total: usize, module_count: usize) -> String; + + /// Format the header for a module + /// + /// # Arguments + /// * `module_name` - Name of the module + /// * `module_file` - File path associated with the module (may be empty) + fn format_module_header(&self, module_name: &str, module_file: &str) -> String; + + /// Format the header for a module with access to its entries for aggregation + /// + /// Default implementation delegates to `format_module_header`. + /// Override this to include aggregated data from entries in the module header. + /// + /// # Arguments + /// * `module_name` - Name of the module + /// * `module_file` - File path associated with the module (may be empty) + /// * `entries` - Reference to the entries in this module + fn format_module_header_with_entries( + &self, + module_name: &str, + module_file: &str, + entries: &[Self::Entry], + ) -> String { + let _ = entries; // Silence unused warning for default implementation + self.format_module_header(module_name, module_file) + } + + /// Format a single entry within a module + /// + /// # Arguments + /// * `entry` - The entry to format + /// * `module_name` - Name of the parent module (for context) + /// * `module_file` - File path of the parent module (for context) + fn format_entry(&self, entry: &Self::Entry, module_name: &str, module_file: &str) -> String; + + /// Format optional detail lines for an entry + /// + /// Default implementation returns empty vec. Override to add details like calls/callers. + fn format_entry_details( + &self, + _entry: &Self::Entry, + _module_name: &str, + _module_file: &str, + ) -> Vec { + Vec::new() + } + + /// Whether to add a blank line after the summary + fn blank_after_summary(&self) -> bool { + true + } + + /// Whether to add a blank line before each module header + fn blank_before_module(&self) -> bool { + false + } +} + +/// Format module-grouped results as a table. +/// +/// This is the shared implementation for both ModuleGroupResult and ModuleCollectionResult. +/// Extracts the common logic to avoid duplication between the two impl blocks. +fn format_module_table(formatter: &F, items: &[crate::types::ModuleGroup], total_items: usize) -> String +where + F: TableFormatter, +{ + let mut lines = Vec::new(); + + lines.push(formatter.format_header()); + lines.push(String::new()); + + if items.is_empty() { + lines.push(formatter.format_empty_message()); + return lines.join("\n"); + } + + lines.push(formatter.format_summary(total_items, items.len())); + if formatter.blank_after_summary() { + lines.push(String::new()); + } + + for module in items { + if formatter.blank_before_module() { + lines.push(String::new()); + } + + lines.push(formatter.format_module_header_with_entries( + &module.name, + &module.file, + &module.entries, + )); + + for entry in &module.entries { + lines.push(format!( + " {}", + formatter.format_entry(entry, &module.name, &module.file) + )); + + for detail in formatter.format_entry_details(entry, &module.name, &module.file) { + lines.push(format!(" {}", detail)); + } + } + } + + lines.join("\n") +} + +/// Default implementation of Outputable for ModuleGroupResult using TableFormatter +impl Outputable for ModuleGroupResult +where + E: Serialize, + ModuleGroupResult: TableFormatter, +{ + fn to_table(&self) -> String { + format_module_table(self, &self.items, self.total_items) + } +} + +/// Default implementation of Outputable for ModuleCollectionResult using TableFormatter +impl Outputable for ModuleCollectionResult +where + E: Serialize, + ModuleCollectionResult: TableFormatter, +{ + fn to_table(&self) -> String { + format_module_table(self, &self.items, self.total_items) + } +} diff --git a/cli/src/test_macros.rs b/cli/src/test_macros.rs new file mode 100644 index 0000000..021ee6d --- /dev/null +++ b/cli/src/test_macros.rs @@ -0,0 +1,658 @@ +//! Declarative macros for generating CLI parsing tests. +//! +//! This module provides macros to reduce boilerplate in CLI argument parsing tests. +//! Instead of writing repetitive test functions, you can declare the test cases +//! and let the macro generate the actual test code. + +/// Generate a test for default values when a command is invoked with minimal args. +#[macro_export] +macro_rules! cli_defaults_test { + ( + command: $cmd:literal, + variant: $variant:ident, + required_args: [$($req_arg:literal),*], + defaults: { + $($($def_field:ident).+ : $def_expected:expr),* $(,)? + } $(,)? + ) => { + #[rstest] + fn test_defaults() { + let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); + match args.command { + crate::commands::Command::$variant(cmd) => { + $( + assert_eq!(cmd.$($def_field).+, $def_expected, + concat!("Default value mismatch for field: ", stringify!($($def_field).+))); + )* + } + _ => panic!(concat!("Expected ", stringify!($variant), " command")), + } + } + }; +} + +/// Generate a single CLI option test. +#[macro_export] +macro_rules! cli_option_test { + ( + command: $cmd:literal, + variant: $variant:ident, + test_name: $test_name:ident, + args: [$($arg:literal),+], + field: $($field:ident).+, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name() { + let args = Args::try_parse_from([ + "code_search", + $cmd, + $($arg),+ + ]).unwrap(); + match args.command { + crate::commands::Command::$variant(cmd) => { + assert_eq!(cmd.$($field).+, $expected, + concat!("Field ", stringify!($($field).+), " mismatch")); + } + _ => panic!(concat!("Expected ", stringify!($variant), " command")), + } + } + }; +} + +/// Generate a single CLI option test with required args. +#[macro_export] +macro_rules! cli_option_test_with_required { + ( + command: $cmd:literal, + variant: $variant:ident, + required_args: [$($req_arg:literal),+], + test_name: $test_name:ident, + args: [$($arg:literal),+], + field: $($field:ident).+, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name() { + let args = Args::try_parse_from([ + "code_search", + $cmd, + $($req_arg,)+ + $($arg),+ + ]).unwrap(); + match args.command { + crate::commands::Command::$variant(cmd) => { + assert_eq!(cmd.$($field).+, $expected, + concat!("Field ", stringify!($($field).+), " mismatch")); + } + _ => panic!(concat!("Expected ", stringify!($variant), " command")), + } + } + }; +} + +/// Generate limit validation tests (zero rejected, max exceeded rejected, default value). +#[macro_export] +macro_rules! cli_limit_tests { + ( + command: $cmd:literal, + variant: $variant:ident, + required_args: [$($req_arg:literal),*], + limit: { + field: $($limit_field:ident).+, + default: $limit_default:expr, + max: $limit_max:expr $(,)? + } $(,)? + ) => { + #[rstest] + fn test_limit_default() { + let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); + match args.command { + crate::commands::Command::$variant(cmd) => { + assert_eq!(cmd.$($limit_field).+, $limit_default); + } + _ => panic!(concat!("Expected ", stringify!($variant), " command")), + } + } + + #[rstest] + fn test_limit_zero_rejected() { + let result = Args::try_parse_from([ + "code_search", + $cmd, + $($req_arg,)* + "--limit", + "0" + ]); + assert!(result.is_err(), "Limit of 0 should be rejected"); + } + + #[rstest] + fn test_limit_exceeds_max_rejected() { + let max_plus_one = ($limit_max + 1).to_string(); + let result = Args::try_parse_from([ + "code_search", + $cmd, + $($req_arg,)* + "--limit", + &max_plus_one + ]); + assert!(result.is_err(), + concat!("Limit exceeding ", stringify!($limit_max), " should be rejected")); + } + }; +} + +/// Generate a test that verifies a command requires a specific argument. +/// +/// # Example +/// +/// ```ignore +/// cli_required_arg_test! { +/// command: "search", +/// test_name: test_requires_pattern, +/// required_arg: "--pattern", +/// } +/// ``` +#[macro_export] +macro_rules! cli_required_arg_test { + ( + command: $cmd:literal, + test_name: $test_name:ident, + required_arg: $arg:literal $(,)? + ) => { + #[rstest] + fn $test_name() { + let result = Args::try_parse_from(["code_search", $cmd]); + assert!(result.is_err(), concat!("Command should require ", $arg)); + assert!( + result.unwrap_err().to_string().contains($arg), + concat!("Error should mention ", $arg) + ); + } + }; +} + +/// Generate a test that verifies parsing fails with specific invalid args. +/// +/// # Example +/// +/// ```ignore +/// cli_error_test! { +/// command: "search", +/// test_name: test_limit_zero_rejected, +/// args: ["--pattern", "test", "--limit", "0"], +/// } +/// ``` +#[macro_export] +macro_rules! cli_error_test { + ( + command: $cmd:literal, + test_name: $test_name:ident, + args: [$($arg:literal),+] $(,)? + ) => { + #[rstest] + fn $test_name() { + let result = Args::try_parse_from([ + "code_search", + $cmd, + $($arg),+ + ]); + assert!(result.is_err()); + } + }; +} + +// ============================================================================= +// Execute Test Macros +// ============================================================================= + +/// Generate a fixture that creates a populated test database. +/// +/// This creates the standard `populated_db` fixture used by execute tests. +/// For inline JSON content. +#[macro_export] +macro_rules! execute_test_fixture { + ( + fixture_name: $name:ident, + json: $json:expr, + project: $project:literal $(,)? + ) => { + #[fixture] + fn $name() -> cozo::DbInstance { + crate::test_utils::setup_test_db($json, $project) + } + }; +} + +/// Generate a fixture using a shared fixture file. +/// +/// Available fixtures: `call_graph`, `type_signatures`, `structs` +/// +/// # Example +/// ```ignore +/// crate::shared_fixture! { +/// fixture_name: populated_db, +/// fixture_type: call_graph, +/// project: "test_project", +/// } +/// ``` +#[macro_export] +macro_rules! shared_fixture { + ( + fixture_name: $name:ident, + fixture_type: call_graph, + project: $project:literal $(,)? + ) => { + #[fixture] + fn $name() -> cozo::DbInstance { + crate::test_utils::call_graph_db($project) + } + }; + ( + fixture_name: $name:ident, + fixture_type: type_signatures, + project: $project:literal $(,)? + ) => { + #[fixture] + fn $name() -> cozo::DbInstance { + crate::test_utils::type_signatures_db($project) + } + }; + ( + fixture_name: $name:ident, + fixture_type: structs, + project: $project:literal $(,)? + ) => { + #[fixture] + fn $name() -> cozo::DbInstance { + crate::test_utils::structs_db($project) + } + }; +} + +/// Generate a test that verifies command execution against an empty database fails. +#[macro_export] +macro_rules! execute_empty_db_test { + ( + cmd_type: $cmd_type:ty, + cmd: $cmd:expr $(,)? + ) => { + #[rstest] + fn test_empty_db() { + let result = crate::test_utils::execute_on_empty_db($cmd); + assert!(result.is_err()); + } + }; +} + +/// Generate an execute test with custom assertions. +/// +/// This is the core macro for execute tests. It handles the boilerplate of +/// executing a command against a fixture and lets you write custom assertions. +/// +/// # Example +/// ```ignore +/// execute_test! { +/// test_name: test_search_finds_modules, +/// fixture: populated_db, +/// cmd: SearchCmd { +/// pattern: "MyApp".to_string(), +/// kind: SearchKind::Modules, +/// project: "test_project".to_string(), +/// limit: 100, +/// regex: false, +/// }, +/// assertions: |result| { +/// assert_eq!(result.modules.len(), 2); +/// assert_eq!(result.kind, "modules"); +/// }, +/// } +/// ``` +#[macro_export] +macro_rules! execute_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + assertions: |$result:ident| $assertions:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let $result = $cmd.execute(&$fixture).expect("Execute should succeed"); + $assertions + } + }; +} + +/// Generate a test that verifies command returns empty results for no match. +/// +/// # Example +/// ```ignore +/// execute_no_match_test! { +/// test_name: test_search_no_match, +/// fixture: populated_db, +/// cmd: SearchCmd { pattern: "NonExistent".into(), ... }, +/// empty_field: modules, +/// } +/// ``` +#[macro_export] +macro_rules! execute_no_match_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + empty_field: $field:ident $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert!(result.$field.is_empty(), concat!(stringify!($field), " should be empty")); + } + }; +} + +/// Generate a test that verifies result count. +/// +/// # Example +/// ```ignore +/// execute_count_test! { +/// test_name: test_search_finds_two, +/// fixture: populated_db, +/// cmd: SearchCmd { ... }, +/// field: modules, +/// expected: 2, +/// } +/// ``` +#[macro_export] +macro_rules! execute_count_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + field: $field:ident, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert_eq!(result.$field.len(), $expected, + concat!("Expected ", stringify!($expected), " ", stringify!($field))); + } + }; +} + +/// Generate a test that verifies a field value on the result. +/// +/// # Example +/// ```ignore +/// execute_field_test! { +/// test_name: test_search_kind, +/// fixture: populated_db, +/// cmd: SearchCmd { kind: SearchKind::Modules, ... }, +/// field: kind, +/// expected: "modules", +/// } +/// ``` +#[macro_export] +macro_rules! execute_field_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + field: $field:ident, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert_eq!(result.$field, $expected, + concat!("Field ", stringify!($field), " mismatch")); + } + }; +} + +/// Generate a test that verifies a field on the first result item. +/// +/// # Example +/// ```ignore +/// execute_first_item_test! { +/// test_name: test_first_function_name, +/// fixture: populated_db, +/// cmd: SearchCmd { ... }, +/// collection: functions, +/// field: name, +/// expected: "get_user", +/// } +/// ``` +#[macro_export] +macro_rules! execute_first_item_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + collection: $collection:ident, + field: $field:ident, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert!(!result.$collection.is_empty(), concat!(stringify!($collection), " should not be empty")); + assert_eq!(result.$collection[0].$field, $expected, + concat!("First item ", stringify!($field), " mismatch")); + } + }; +} + +/// Generate a test that verifies all items match a condition. +/// +/// # Example +/// ```ignore +/// execute_all_match_test! { +/// test_name: test_all_from_project, +/// fixture: populated_db, +/// cmd: SearchCmd { project: "test_project".into(), ... }, +/// collection: modules, +/// condition: |item| item.project == "test_project", +/// } +/// ``` +#[macro_export] +macro_rules! execute_all_match_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + collection: $collection:ident, + condition: |$item:ident| $cond:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert!(result.$collection.iter().all(|$item| $cond), + concat!("Not all ", stringify!($collection), " matched condition")); + } + }; +} + +/// Generate a test that verifies limit is respected. +/// +/// # Example +/// ```ignore +/// execute_limit_test! { +/// test_name: test_respects_limit, +/// fixture: populated_db, +/// cmd: SearchCmd { limit: 1, ... }, +/// collection: modules, +/// limit: 1, +/// } +/// ``` +#[macro_export] +macro_rules! execute_limit_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + cmd: $cmd:expr, + collection: $collection:ident, + limit: $limit:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: cozo::DbInstance) { + use crate::commands::Execute; + let result = $cmd.execute(&$fixture).expect("Execute should succeed"); + assert!(result.$collection.len() <= $limit, + concat!("Expected at most ", stringify!($limit), " ", stringify!($collection))); + } + }; +} + +// ============================================================================= +// Output Test Macros +// ============================================================================= + +/// Generate a test that verifies table output matches expected string. +/// +/// Works with rstest fixtures by accepting a fixture parameter. +/// +/// # Example +/// ```ignore +/// output_table_test! { +/// test_name: test_to_table_empty, +/// fixture: empty_result, +/// fixture_type: SearchResult, +/// expected: EMPTY_TABLE_OUTPUT, +/// } +/// ``` +#[macro_export] +macro_rules! output_table_test { + // With format parameter (Json, Toon) + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + fixture_type: $fixture_type:ty, + expected: $expected:expr, + format: $format:ident $(,)? + ) => { + #[rstest] + fn $test_name($fixture: $fixture_type) { + use crate::output::{Outputable, OutputFormat}; + assert_eq!($fixture.format(OutputFormat::$format), $expected); + } + }; + // Default table format + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + fixture_type: $fixture_type:ty, + expected: $expected:expr $(,)? + ) => { + #[rstest] + fn $test_name($fixture: $fixture_type) { + use crate::output::Outputable; + assert_eq!($fixture.to_table(), $expected); + } + }; +} + +/// Generate a test that verifies table output contains expected strings. +/// +/// Use this when exact string matching is too brittle. +#[macro_export] +macro_rules! output_table_contains_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + fixture_type: $fixture_type:ty, + contains: [$($needle:literal),* $(,)?] $(,)? + ) => { + #[rstest] + fn $test_name($fixture: $fixture_type) { + use crate::output::Outputable; + let output = $fixture.to_table(); + $( + assert!(output.contains($needle), concat!("Table output should contain: ", $needle)); + )* + } + }; +} + +/// Generate a test that verifies JSON output is valid and contains expected fields. +/// +/// # Example +/// ```ignore +/// output_json_test! { +/// test_name: test_format_json, +/// fixture: single_result, +/// fixture_type: SearchResult, +/// assertions: { +/// "pattern": "MyApp", +/// "modules".len(): 2, +/// }, +/// } +/// ``` +#[macro_export] +macro_rules! output_json_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + fixture_type: $fixture_type:ty, + assertions: { $($field:literal : $expected:expr),* $(,)? } $(,)? + ) => { + #[rstest] + fn $test_name($fixture: $fixture_type) { + use crate::output::{Outputable, OutputFormat}; + let output = $fixture.format(OutputFormat::Json); + let parsed: serde_json::Value = serde_json::from_str(&output) + .expect("Should produce valid JSON"); + $( + assert_eq!(parsed[$field], $expected, concat!("JSON field mismatch: ", $field)); + )* + } + }; +} + +/// Generate a test that verifies Toon output contains expected strings. +/// +/// # Example +/// ```ignore +/// output_toon_test! { +/// test_name: test_format_toon, +/// fixture: single_result, +/// fixture_type: SearchResult, +/// contains: ["pattern: MyApp", "modules["], +/// } +/// ``` +#[macro_export] +macro_rules! output_toon_test { + ( + test_name: $test_name:ident, + fixture: $fixture:ident, + fixture_type: $fixture_type:ty, + contains: [$($needle:literal),* $(,)?] $(,)? + ) => { + #[rstest] + fn $test_name($fixture: $fixture_type) { + use crate::output::{Outputable, OutputFormat}; + let output = $fixture.format(OutputFormat::Toon); + $( + assert!(output.contains($needle), concat!("Toon output should contain: ", $needle)); + )* + } + }; +} + +#[cfg(test)] +mod tests { + //! Tests for the test macros themselves. + //! + //! These verify that the macros compile and generate working tests. + + // We can't easily test macros here since they generate test functions, + // but we can at least verify they compile by using them in actual test modules. +} diff --git a/cli/src/utils.rs b/cli/src/utils.rs new file mode 100644 index 0000000..b156fef --- /dev/null +++ b/cli/src/utils.rs @@ -0,0 +1,490 @@ +//! Utility functions for code search CLI output and presentation. + +use std::collections::BTreeMap; +use regex::Regex; +use db::types::{ModuleGroup, Call}; +use crate::dedup::sort_and_deduplicate; + +/// Groups items by module into a structured result +/// +/// Transforms a vector of source items into (module, entry) tuples and groups them by module +/// using BTreeMap for consistent ordering. Files default to empty string. +/// +/// # Arguments +/// * `items` - Vector of items to transform and group +/// * `transform` - Closure that converts source items to (module_name, entry) tuples +/// +/// # Returns +/// A vector of ModuleGroup structs, one per module in sorted order +pub fn group_by_module(items: Vec, transform: F) -> Vec> +where + F: Fn(T) -> (String, E), +{ + group_by_module_with_file(items, |item| { + let (module, entry) = transform(item); + (module, entry, String::new()) + }) +} + +/// Groups items by module with optional file tracking +/// +/// Like `group_by_module` but allows specifying a file path for each item. +/// +/// # Arguments +/// * `items` - Vector of items to transform and group +/// * `transform` - Closure that converts source items to (module_name, entry, file) tuples +/// +/// # Returns +/// A vector of ModuleGroup structs, one per module in sorted order +pub fn group_by_module_with_file(items: Vec, transform: F) -> Vec> +where + F: Fn(T) -> (String, E, String), +{ + let mut module_map: BTreeMap)> = BTreeMap::new(); + + for item in items { + let (module, entry, file) = transform(item); + let entry_data = module_map + .entry(module) + .or_insert_with(|| (file.clone(), Vec::new())); + entry_data.1.push(entry); + } + + module_map + .into_iter() + .map(|(name, (file, entries))| ModuleGroup { name, file, entries, function_count: None }) + .collect() +} + +/// Groups calls by module and function key, applying sort/deduplicate to each group. +/// +/// This is the primary helper for processing call data that follows this pattern: +/// 1. Receive Vec from a query +/// 2. Group by module and function key using closures +/// 3. Apply sort_and_deduplicate to each function's calls +/// 4. Convert to ModuleGroupResult using entry_fn and file_fn +/// +/// # Arguments +/// * `calls` - Vector of Call objects to group +/// * `module_fn` - Closure that extracts the module name from a Call +/// * `key_fn` - Closure that extracts the grouping key (e.g., function info) from a Call +/// * `sort_cmp` - Comparator closure for sorting calls (e.g., by line number) +/// * `dedup_key` - Closure that extracts the deduplication key from a Call +/// * `entry_fn` - Closure that converts (key, sorted/deduped calls) to an entry +/// * `file_fn` - Closure that determines the file path for a module group +/// +/// # Returns +/// A tuple of (total_items_count, Vec>) +/// +/// # Example +/// ```ignore +/// let (total, groups) = group_calls( +/// calls, +/// |call| call.caller.module.clone(), // group by caller module +/// |call| (call.caller.name.clone(), call.caller.arity), // key by (name, arity) +/// |a, b| a.line.cmp(&b.line), // sort by line +/// |c| (c.callee.module.clone(), c.callee.name.clone()), // dedup by callee +/// |(name, arity), calls| MyEntry { name, arity, calls }, // build entry +/// |_module, _map| String::new(), // no file tracking +/// ); +/// ``` +pub fn group_calls( + calls: Vec, + module_fn: MF, + key_fn: KF, + sort_cmp: SC, + dedup_key: DK, + entry_fn: EF, + file_fn: FF, +) -> (usize, Vec>) +where + K: Ord, + MF: Fn(&Call) -> String, + KF: Fn(&Call) -> K, + SC: FnMut(&Call, &Call) -> std::cmp::Ordering + Clone, + DK: Fn(&Call) -> D + Clone, + D: Eq + std::hash::Hash, + EF: Fn(K, Vec) -> E, + FF: Fn(&str, &BTreeMap>) -> String, +{ + // Group by module -> key -> calls + let mut by_module: BTreeMap>> = BTreeMap::new(); + for call in calls { + let module = module_fn(&call); + let key = key_fn(&call); + by_module.entry(module).or_default().entry(key).or_default().push(call); + } + + // Convert to ModuleGroups with sort/dedup, counting total after dedup + let mut total_items = 0; + let items = by_module.into_iter().map(|(module_name, mut functions_map)| { + let file = file_fn(&module_name, &functions_map); + + // Sort and deduplicate each function's calls + for calls in functions_map.values_mut() { + sort_and_deduplicate(calls, sort_cmp.clone(), dedup_key.clone()); + total_items += calls.len(); + } + + let entries: Vec = functions_map.into_iter() + .map(|(key, calls)| entry_fn(key, calls)) + .collect(); + + ModuleGroup { name: module_name, file, entries, function_count: None } + }).collect(); + + (total_items, items) +} + +/// Converts a two-level nested map into Vec>. +/// +/// Handles the common pattern of grouping calls by module and function, +/// then converting the nested structure into a flat Vec of ModuleGroups. +/// +/// # Arguments +/// * `by_module` - A BTreeMap of modules to (function_key → calls) maps +/// * `entry_builder` - Closure that converts (function_key, calls) to an entry +/// * `file_strategy` - Closure that determines the file path for a module group +/// +/// # Returns +/// A vector of ModuleGroup structs, one per module in sorted order +/// +/// # Example +/// ```ignore +/// let mut by_module: BTreeMap>> = /* ... */; +/// let groups = convert_to_module_groups( +/// by_module, +/// |(name, arity), calls| { +/// CallEntry { +/// function_name: name, +/// arity, +/// count: calls.len(), +/// } +/// }, +/// |_module, _map| String::new() // No file tracking +/// ); +/// ``` +pub fn convert_to_module_groups( + by_module: BTreeMap>>, + entry_builder: F, + file_strategy: FileF, +) -> Vec> +where + FK: Ord, + F: Fn(FK, Vec) -> E, + FileF: Fn(&str, &BTreeMap>) -> String, +{ + by_module + .into_iter() + .map(|(module_name, functions_map)| { + let file = file_strategy(&module_name, &functions_map); + + let entries: Vec = functions_map + .into_iter() + .map(|(key, calls)| entry_builder(key, calls)) + .collect(); + + ModuleGroup { + name: module_name, + file, + entries, + function_count: None, + } + }) + .collect() +} + +// ============================================================================= +// Type Formatting Utilities +// ============================================================================= + +/// Formats an Elixir type definition for display. +/// +/// Transforms struct type definitions from the internal representation: +/// `@type t() :: %{__struct__: ModuleName, field1: type1, field2: type2}` +/// +/// To the more readable Elixir syntax: +/// ```text +/// @type t() :: %ModuleName{ +/// field1: type1, +/// field2: type2 +/// } +/// ``` +/// +/// # Arguments +/// * `definition` - The raw type definition string from the database +/// +/// # Returns +/// The formatted type definition string +pub fn format_type_definition(definition: &str) -> String { + // Check if this is a struct type definition + if let Some(formatted) = try_format_struct_type(definition) { + return formatted; + } + + // Return as-is if no transformation needed + definition.to_string() +} + +/// Attempts to format a struct type definition. +/// +/// Returns `Some(formatted_string)` if the definition contains a struct pattern, +/// otherwise returns `None`. +fn try_format_struct_type(definition: &str) -> Option { + // Pattern to match: %{__struct__: ModuleName} or %{__struct__: ModuleName, ...} + // This captures the struct module name and optionally the remaining fields + let struct_pattern = Regex::new( + r"%\{\s*__struct__:\s*([A-Za-z][A-Za-z0-9_.]*(?:\.[A-Za-z][A-Za-z0-9_]*)*)\s*(?:,\s*(.*))?\}" + ).ok()?; + + if let Some(caps) = struct_pattern.captures(definition) { + let module_name = caps.get(1)?.as_str(); + let fields_str = caps.get(2).map(|m| m.as_str().trim()).unwrap_or(""); + + // Parse the fields + let fields = parse_type_fields(fields_str); + + if fields.is_empty() { + // Empty struct + let formatted_struct = format!("%{}{{}}", module_name); + return Some(definition.replace(caps.get(0)?.as_str(), &formatted_struct)); + } + + // Format with multi-line for readability + let formatted_fields = fields + .iter() + .map(|(name, typ)| format!(" {}: {}", name, typ)) + .collect::>() + .join(",\n"); + + let formatted_struct = format!("%{}{{\n{}\n}}", module_name, formatted_fields); + + // Replace the struct pattern in the original definition + Some(definition.replace(caps.get(0)?.as_str(), &formatted_struct)) + } else { + None + } +} + +/// Parses a comma-separated list of type fields. +/// +/// Handles nested types with parentheses, braces, and brackets. +/// For example: `name: String.t(), list: list(integer()), map: map()` +/// +/// # Arguments +/// * `fields_str` - The raw fields string without outer braces +/// +/// # Returns +/// A vector of (field_name, field_type) tuples +fn parse_type_fields(fields_str: &str) -> Vec<(String, String)> { + let mut fields = Vec::new(); + let mut current_field = String::new(); + let mut depth = 0; // Track nesting depth for (), {}, [] + + for ch in fields_str.chars() { + match ch { + '(' | '{' | '[' => { + depth += 1; + current_field.push(ch); + } + ')' | '}' | ']' => { + depth -= 1; + current_field.push(ch); + } + ',' if depth == 0 => { + // Top-level comma - this is a field separator + if let Some((name, typ)) = parse_single_field(¤t_field) { + fields.push((name, typ)); + } + current_field.clear(); + } + _ => { + current_field.push(ch); + } + } + } + + // Don't forget the last field + if let Some((name, typ)) = parse_single_field(¤t_field) { + fields.push((name, typ)); + } + + fields +} + +/// Parses a single field definition like "name: String.t()" or "count: integer()". +/// +/// # Arguments +/// * `field_str` - A single field definition string +/// +/// # Returns +/// `Some((field_name, field_type))` if parsing succeeds, `None` otherwise +fn parse_single_field(field_str: &str) -> Option<(String, String)> { + let trimmed = field_str.trim(); + if trimmed.is_empty() { + return None; + } + + // Find the first colon that separates field name from type + let colon_pos = trimmed.find(':')?; + let name = trimmed[..colon_pos].trim().to_string(); + let typ = trimmed[colon_pos + 1..].trim().to_string(); + + if name.is_empty() || typ.is_empty() { + return None; + } + + Some((name, typ)) +} + +#[cfg(test)] +mod tests { + use super::*; + + // Type formatting tests + #[test] + fn test_format_simple_struct_type() { + let input = "@type t() :: %{__struct__: MyApp.User, name: String.t(), age: integer()}"; + let result = format_type_definition(input); + + assert!(result.contains("%MyApp.User{")); + assert!(result.contains("name: String.t()")); + assert!(result.contains("age: integer()")); + } + + #[test] + fn test_format_struct_with_nested_types() { + let input = "@type t() :: %{__struct__: TradeGym.DataImporter, executions: list(), open_positions: list(), reason: String.t() | nil, status: :ok | :error}"; + let result = format_type_definition(input); + + assert!(result.contains("%TradeGym.DataImporter{")); + assert!(result.contains("executions: list()")); + assert!(result.contains("open_positions: list()")); + assert!(result.contains("reason: String.t() | nil")); + assert!(result.contains("status: :ok | :error")); + } + + #[test] + fn test_format_empty_struct() { + let input = "@type t() :: %{__struct__: MyApp.Empty}"; + let result = format_type_definition(input); + + // Empty struct should remain compact + assert!(result.contains("%MyApp.Empty{}")); + } + + #[test] + fn test_non_struct_type_unchanged() { + let input = "@type user_id() :: integer()"; + let result = format_type_definition(input); + + assert_eq!(result, input); + } + + #[test] + fn test_map_type_unchanged() { + let input = "@type options() :: %{name: String.t(), age: integer()}"; + let result = format_type_definition(input); + + // Regular maps (without __struct__) should remain unchanged + assert_eq!(result, input); + } + + #[test] + fn test_format_struct_with_complex_types() { + let input = "@type t() :: %{__struct__: MyApp.State, callbacks: list({atom(), function()}), data: map()}"; + let result = format_type_definition(input); + + assert!(result.contains("%MyApp.State{")); + assert!(result.contains("callbacks: list({atom(), function()})")); + assert!(result.contains("data: map()")); + } + + #[test] + fn test_parse_type_fields_simple() { + let input = "name: String.t(), age: integer()"; + let fields = parse_type_fields(input); + + assert_eq!(fields.len(), 2); + assert_eq!(fields[0], ("name".to_string(), "String.t()".to_string())); + assert_eq!(fields[1], ("age".to_string(), "integer()".to_string())); + } + + #[test] + fn test_parse_type_fields_with_nested_parens() { + let input = "list: list(integer()), map: map()"; + let fields = parse_type_fields(input); + + assert_eq!(fields.len(), 2); + assert_eq!(fields[0], ("list".to_string(), "list(integer())".to_string())); + assert_eq!(fields[1], ("map".to_string(), "map()".to_string())); + } + + #[test] + fn test_parse_type_fields_with_union_types() { + let input = "status: :ok | :error, reason: String.t() | nil"; + let fields = parse_type_fields(input); + + assert_eq!(fields.len(), 2); + assert_eq!(fields[0], ("status".to_string(), ":ok | :error".to_string())); + assert_eq!(fields[1], ("reason".to_string(), "String.t() | nil".to_string())); + } + + #[test] + fn test_opaque_type_unchanged() { + let input = "@opaque state() :: %{internal: map()}"; + let result = format_type_definition(input); + + assert_eq!(result, input); + } + + #[test] + fn test_typep_with_struct() { + let input = "@typep t() :: %{__struct__: MyApp.Internal, data: term()}"; + let result = format_type_definition(input); + + assert!(result.contains("%MyApp.Internal{")); + assert!(result.contains("data: term()")); + } + + // Grouping tests + #[test] + fn test_group_by_module_empty() { + let items: Vec<(String, i32)> = vec![]; + let result = group_by_module(items, |(module, item)| (module, item)); + assert_eq!(result.len(), 0); + } + + #[test] + fn test_group_by_module_single_module() { + let items = vec![ + ("math".to_string(), 1), + ("math".to_string(), 2), + ("math".to_string(), 3), + ]; + let result = group_by_module(items, |(module, item)| (module, item)); + assert_eq!(result.len(), 1); + assert_eq!(result[0].name, "math"); + assert_eq!(result[0].entries.len(), 3); + } + + #[test] + fn test_group_by_module_multiple_modules() { + let items = vec![ + ("math".to_string(), 1), + ("string".to_string(), 2), + ("math".to_string(), 3), + ("list".to_string(), 4), + ("string".to_string(), 5), + ]; + let result = group_by_module(items, |(module, item)| (module, item)); + assert_eq!(result.len(), 3); + // Verify sorted order (BTreeMap sorts) + assert_eq!(result[0].name, "list"); + assert_eq!(result[1].name, "math"); + assert_eq!(result[2].name, "string"); + // Verify items are grouped correctly + assert_eq!(result[1].entries.len(), 2); // math has 2 items + assert_eq!(result[2].entries.len(), 2); // string has 2 items + } +} From 4f534ce75fc571719fbfea19c20651e5e094fd3d Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Tue, 23 Dec 2025 00:24:02 +0100 Subject: [PATCH 7/8] Update all CLI imports to reference db crate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements ticket 7 of 8 - Update CLI import paths. This is the critical integration ticket that connects the cli crate to the db crate. Changes (100+ files modified): Core files: - cli/src/main.rs: Remove pub mod types, import db::open_db - cli/src/commands/mod.rs: Use db::DbInstance in Execute trait - cli/src/output.rs: Import db::types::ModuleGroupResult - cli/src/utils.rs: Import db::types::{ModuleGroup, Call} All 27 commands updated: - execute.rs files: crate::queries::* → db::queries::* - execute.rs files: crate::types::* → db::types::* - mod.rs files: cozo::DbInstance → db::DbInstance - output.rs files: crate::types::* → db::types::* - test files: Updated imports to use db:: prefix Commands updated: - accepts, boundaries, browse_module, calls_from, calls_to - clusters, complexity, cycles, depended_by, depends_on - describe, duplicates, function, god_modules, hotspots - import, large_functions, location, many_clauses, path - returns, reverse_trace, search, setup, struct_usage - trace, unused Orphan rule fixes (impl blocks on external types): Converted 11 impl blocks to standalone builder functions: - build_accepts_result() (accepts) - build_calls_from_result() (calls_from) - build_callee_result() (calls_to) - build_trace_result() (trace) - build_dependent_caller_result() (depended_by) - build_dependency_result() (depends_on) - build_function_signatures_result() (function) - build_return_info_result() (returns) - build_reverse_trace_result() (reverse_trace) - build_usage_info_result() + build_struct_modules_result() (struct_usage) - build_unused_functions_result() (unused) Database crate updates: - db/src/lib.rs: Re-export DbInstance for convenient access - Added cozo to db crate public API Import statistics: - 0 remaining crate::queries or crate::types references - 81+ new db:: imports added across all command files Verification: - cargo build: ✓ SUCCESS - rg "use crate::(queries|types)" cli/src/: no matches - All imports now properly reference db crate The workspace is now fully integrated with proper crate boundaries. The entire workspace compiles successfully. Relates to ticket: scratch/tickets/07-update-imports.md --- Cargo.lock | 5 + cli/Cargo.toml | 1 + cli/src/commands/accepts/execute.rs | 55 +++-- cli/src/commands/accepts/mod.rs | 2 +- cli/src/commands/accepts/output.rs | 2 +- cli/src/commands/boundaries/execute.rs | 6 +- cli/src/commands/boundaries/mod.rs | 2 +- cli/src/commands/boundaries/output.rs | 2 +- cli/src/commands/browse_module/execute.rs | 10 +- cli/src/commands/browse_module/mod.rs | 2 +- .../commands/browse_module/output_tests.rs | 2 +- cli/src/commands/calls_from/execute.rs | 93 ++++---- cli/src/commands/calls_from/mod.rs | 2 +- cli/src/commands/calls_from/output.rs | 2 +- cli/src/commands/calls_from/output_tests.rs | 141 +++++++----- cli/src/commands/calls_to/execute.rs | 90 ++++---- cli/src/commands/calls_to/mod.rs | 2 +- cli/src/commands/calls_to/output.rs | 2 +- cli/src/commands/calls_to/output_tests.rs | 67 ++++-- cli/src/commands/clusters/execute.rs | 4 +- cli/src/commands/clusters/mod.rs | 2 +- cli/src/commands/complexity/execute.rs | 6 +- cli/src/commands/complexity/mod.rs | 2 +- cli/src/commands/complexity/output.rs | 2 +- cli/src/commands/complexity/output_tests.rs | 2 +- cli/src/commands/cycles/execute.rs | 4 +- cli/src/commands/cycles/mod.rs | 2 +- cli/src/commands/depended_by/execute.rs | 160 +++++++------- cli/src/commands/depended_by/mod.rs | 2 +- cli/src/commands/depended_by/output.rs | 2 +- cli/src/commands/depended_by/output_tests.rs | 8 +- cli/src/commands/depends_on/execute.rs | 90 ++++---- cli/src/commands/depends_on/mod.rs | 2 +- cli/src/commands/depends_on/output.rs | 2 +- cli/src/commands/depends_on/output_tests.rs | 8 +- cli/src/commands/describe/execute.rs | 2 +- cli/src/commands/describe/mod.rs | 2 +- cli/src/commands/duplicates/execute.rs | 8 +- cli/src/commands/duplicates/mod.rs | 2 +- cli/src/commands/function/execute.rs | 60 +++-- cli/src/commands/function/mod.rs | 2 +- cli/src/commands/function/output.rs | 2 +- cli/src/commands/function/output_tests.rs | 8 +- cli/src/commands/god_modules/execute.rs | 6 +- cli/src/commands/god_modules/mod.rs | 2 +- cli/src/commands/god_modules/output.rs | 2 +- cli/src/commands/hotspots/cli_tests.rs | 2 +- cli/src/commands/hotspots/execute.rs | 12 +- cli/src/commands/hotspots/execute_tests.rs | 16 +- cli/src/commands/hotspots/mod.rs | 4 +- cli/src/commands/import/execute.rs | 8 +- cli/src/commands/import/mod.rs | 2 +- cli/src/commands/import/output.rs | 2 +- cli/src/commands/import/output_tests.rs | 6 +- cli/src/commands/large_functions/execute.rs | 6 +- cli/src/commands/large_functions/mod.rs | 2 +- cli/src/commands/large_functions/output.rs | 2 +- cli/src/commands/location/execute.rs | 4 +- cli/src/commands/location/mod.rs | 2 +- cli/src/commands/location/output_tests.rs | 6 +- cli/src/commands/many_clauses/execute.rs | 6 +- cli/src/commands/many_clauses/mod.rs | 2 +- cli/src/commands/many_clauses/output.rs | 2 +- cli/src/commands/mod.rs | 4 +- cli/src/commands/path/execute.rs | 4 +- cli/src/commands/path/mod.rs | 2 +- cli/src/commands/path/output_tests.rs | 8 +- cli/src/commands/returns/execute.rs | 54 +++-- cli/src/commands/returns/mod.rs | 2 +- cli/src/commands/returns/output.rs | 2 +- cli/src/commands/reverse_trace/execute.rs | 166 +++++++------- cli/src/commands/reverse_trace/mod.rs | 2 +- .../commands/reverse_trace/output_tests.rs | 2 +- cli/src/commands/search/execute.rs | 4 +- cli/src/commands/search/mod.rs | 2 +- cli/src/commands/search/output_tests.rs | 8 +- cli/src/commands/setup/execute.rs | 6 +- cli/src/commands/setup/mod.rs | 2 +- cli/src/commands/struct_usage/execute.rs | 190 ++++++++-------- cli/src/commands/struct_usage/mod.rs | 2 +- cli/src/commands/struct_usage/output.rs | 2 +- cli/src/commands/struct_usage/output_tests.rs | 2 +- cli/src/commands/trace/execute.rs | 209 +++++++++--------- cli/src/commands/trace/mod.rs | 2 +- cli/src/commands/trace/output.rs | 8 +- cli/src/commands/trace/output_tests.rs | 2 +- cli/src/commands/unused/execute.rs | 56 +++-- cli/src/commands/unused/mod.rs | 2 +- cli/src/commands/unused/output.rs | 2 +- cli/src/commands/unused/output_tests.rs | 8 +- cli/src/main.rs | 10 +- cli/src/output.rs | 4 +- cli/src/test_macros.rs | 34 +-- cli/templates/agents/.gitkeep | 0 cli/templates/hooks/.gitkeep | 0 cli/templates/skills/.gitkeep | 0 db/src/lib.rs | 1 + db/src/types/trace.rs | 2 + 98 files changed, 909 insertions(+), 861 deletions(-) create mode 100644 cli/templates/agents/.gitkeep create mode 100644 cli/templates/hooks/.gitkeep create mode 100644 cli/templates/skills/.gitkeep diff --git a/Cargo.lock b/Cargo.lock index 3dbc92f..126cb7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -553,9 +553,14 @@ dependencies = [ name = "db" version = "0.1.0" dependencies = [ + "clap", "cozo", + "include_dir", + "regex", + "rstest", "serde", "serde_json", + "tempfile", "thiserror", ] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 6821720..cc42df6 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -15,6 +15,7 @@ include_dir = "0.7" home = "0.5.12" [dev-dependencies] +db = { path = "../db", features = ["test-utils"] } tempfile = "3" rstest = "0.23" serial_test = "3.2.0" diff --git a/cli/src/commands/accepts/execute.rs b/cli/src/commands/accepts/execute.rs index ece373c..9431f4d 100644 --- a/cli/src/commands/accepts/execute.rs +++ b/cli/src/commands/accepts/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::AcceptsCmd; use crate::commands::Execute; -use crate::queries::accepts::{find_accepts, AcceptsEntry}; -use crate::types::ModuleGroupResult; +use db::queries::accepts::{find_accepts, AcceptsEntry}; +use db::types::ModuleGroupResult; /// A function's input type information #[derive(Debug, Clone, Serialize)] @@ -17,40 +17,37 @@ pub struct AcceptsInfo { pub line: i64, } -impl ModuleGroupResult { - /// Build grouped result from flat AcceptsEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); +fn build_accepts_result( + pattern: String, + module_filter: Option, + entries: Vec, +) -> ModuleGroupResult { + let total_items = entries.len(); - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let accepts_info = AcceptsInfo { - name: entry.name, - arity: entry.arity, - inputs: entry.inputs_string, - return_type: entry.return_string, - line: entry.line, - }; - (entry.module, accepts_info) - }); + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let accepts_info = AcceptsInfo { + name: entry.name, + arity: entry.arity, + inputs: entry.inputs_string, + return_type: entry.return_string, + line: entry.line, + }; + (entry.module, accepts_info) + }); - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, } } impl Execute for AcceptsCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let entries = find_accepts( db, &self.pattern, @@ -60,7 +57,7 @@ impl Execute for AcceptsCmd { self.common.limit, )?; - Ok(>::from_entries( + Ok(build_accepts_result( self.pattern, self.module, entries, diff --git a/cli/src/commands/accepts/mod.rs b/cli/src/commands/accepts/mod.rs index 7e7c191..623d531 100644 --- a/cli/src/commands/accepts/mod.rs +++ b/cli/src/commands/accepts/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/accepts/output.rs b/cli/src/commands/accepts/output.rs index 9d7e44a..d01382a 100644 --- a/cli/src/commands/accepts/output.rs +++ b/cli/src/commands/accepts/output.rs @@ -1,7 +1,7 @@ //! Output formatting for accepts command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::AcceptsInfo; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/boundaries/execute.rs b/cli/src/commands/boundaries/execute.rs index 20120a6..09686ab 100644 --- a/cli/src/commands/boundaries/execute.rs +++ b/cli/src/commands/boundaries/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::BoundariesCmd; use crate::commands::Execute; -use crate::queries::hotspots::{find_hotspots, HotspotKind}; -use crate::types::{ModuleCollectionResult, ModuleGroup}; +use db::queries::hotspots::{find_hotspots, HotspotKind}; +use db::types::{ModuleCollectionResult, ModuleGroup}; /// A single boundary module entry #[derive(Debug, Clone, Serialize)] @@ -18,7 +18,7 @@ pub struct BoundaryEntry { impl Execute for BoundariesCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let hotspots = find_hotspots( db, HotspotKind::Ratio, diff --git a/cli/src/commands/boundaries/mod.rs b/cli/src/commands/boundaries/mod.rs index 7f4e01b..09576ab 100644 --- a/cli/src/commands/boundaries/mod.rs +++ b/cli/src/commands/boundaries/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/boundaries/output.rs b/cli/src/commands/boundaries/output.rs index 8dc4139..439cf92 100644 --- a/cli/src/commands/boundaries/output.rs +++ b/cli/src/commands/boundaries/output.rs @@ -2,7 +2,7 @@ use super::execute::BoundaryEntry; use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; impl TableFormatter for ModuleCollectionResult { type Entry = BoundaryEntry; diff --git a/cli/src/commands/browse_module/execute.rs b/cli/src/commands/browse_module/execute.rs index d239845..0bf4379 100644 --- a/cli/src/commands/browse_module/execute.rs +++ b/cli/src/commands/browse_module/execute.rs @@ -5,10 +5,10 @@ use serde::Serialize; use super::{BrowseModuleCmd, DefinitionKind}; use crate::commands::Execute; -use crate::queries::file::find_functions_in_module; -use crate::queries::specs::find_specs; -use crate::queries::types::find_types; -use crate::queries::structs::{find_struct_fields, group_fields_into_structs, FieldInfo}; +use db::queries::file::find_functions_in_module; +use db::queries::specs::find_specs; +use db::queries::types::find_types; +use db::queries::structs::{find_struct_fields, group_fields_into_structs, FieldInfo}; /// Result of browsing definitions in a module #[derive(Debug, Serialize)] @@ -119,7 +119,7 @@ impl Definition { impl Execute for BrowseModuleCmd { type Output = BrowseModuleResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let mut definitions = Vec::new(); // Determine what to query based on kind filter diff --git a/cli/src/commands/browse_module/mod.rs b/cli/src/commands/browse_module/mod.rs index 791f378..c7cde0c 100644 --- a/cli/src/commands/browse_module/mod.rs +++ b/cli/src/commands/browse_module/mod.rs @@ -1,7 +1,7 @@ use std::error::Error; use clap::{Parser, ValueEnum}; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/browse_module/output_tests.rs b/cli/src/commands/browse_module/output_tests.rs index 2790b4a..425652b 100644 --- a/cli/src/commands/browse_module/output_tests.rs +++ b/cli/src/commands/browse_module/output_tests.rs @@ -4,7 +4,7 @@ mod tests { use super::super::execute::{BrowseModuleResult, Definition}; use super::super::DefinitionKind; - use crate::queries::structs::FieldInfo; + use db::queries::structs::FieldInfo; use rstest::{fixture, rstest}; // ========================================================================= diff --git a/cli/src/commands/calls_from/execute.rs b/cli/src/commands/calls_from/execute.rs index 873afb9..79a01cd 100644 --- a/cli/src/commands/calls_from/execute.rs +++ b/cli/src/commands/calls_from/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::CallsFromCmd; use crate::commands::Execute; -use crate::queries::calls_from::find_calls_from; -use crate::types::{Call, ModuleGroupResult}; +use db::queries::calls_from::find_calls_from; +use db::types::{Call, ModuleGroupResult}; use crate::utils::group_calls; /// A caller function with all its outgoing calls @@ -19,52 +19,49 @@ pub struct CallerFunction { pub calls: Vec, } -impl ModuleGroupResult { - /// Build grouped result from flat calls - pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { - let (total_items, items) = group_calls( +fn build_calls_from_result(module_pattern: String, function_pattern: String, calls: Vec) -> ModuleGroupResult { + let (total_items, items) = group_calls( + calls, + // Group by caller module + |call| call.caller.module.to_string(), + // Key by caller function metadata + |call| CallerFunctionKey { + name: call.caller.name.to_string(), + arity: call.caller.arity, + kind: call.caller.kind.as_deref().unwrap_or("").to_string(), + start_line: call.caller.start_line.unwrap_or(0), + end_line: call.caller.end_line.unwrap_or(0), + }, + // Sort by line number + |a, b| a.line.cmp(&b.line), + // Deduplicate by callee (module, name, arity) + |c| (c.callee.module.to_string(), c.callee.name.to_string(), c.callee.arity), + // Build CallerFunction entry + |key, calls| CallerFunction { + name: key.name, + arity: key.arity, + kind: key.kind, + start_line: key.start_line, + end_line: key.end_line, calls, - // Group by caller module - |call| call.caller.module.to_string(), - // Key by caller function metadata - |call| CallerFunctionKey { - name: call.caller.name.to_string(), - arity: call.caller.arity, - kind: call.caller.kind.as_deref().unwrap_or("").to_string(), - start_line: call.caller.start_line.unwrap_or(0), - end_line: call.caller.end_line.unwrap_or(0), - }, - // Sort by line number - |a, b| a.line.cmp(&b.line), - // Deduplicate by callee (module, name, arity) - |c| (c.callee.module.to_string(), c.callee.name.to_string(), c.callee.arity), - // Build CallerFunction entry - |key, calls| CallerFunction { - name: key.name, - arity: key.arity, - kind: key.kind, - start_line: key.start_line, - end_line: key.end_line, - calls, - }, - // File tracking strategy: extract from first call in first function - |_module, functions_map| { - functions_map - .values() - .next() - .and_then(|calls| calls.first()) - .and_then(|call| call.caller.file.as_deref()) - .unwrap_or("") - .to_string() - }, - ); + }, + // File tracking strategy: extract from first call in first function + |_module, functions_map| { + functions_map + .values() + .next() + .and_then(|calls| calls.first()) + .and_then(|call| call.caller.file.as_deref()) + .unwrap_or("") + .to_string() + }, + ); - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, } } @@ -81,7 +78,7 @@ struct CallerFunctionKey { impl Execute for CallsFromCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let calls = find_calls_from( db, &self.module, @@ -92,7 +89,7 @@ impl Execute for CallsFromCmd { self.common.limit, )?; - Ok(>::from_calls( + Ok(build_calls_from_result( self.module, self.function.unwrap_or_default(), calls, diff --git a/cli/src/commands/calls_from/mod.rs b/cli/src/commands/calls_from/mod.rs index f0713b7..e312c57 100644 --- a/cli/src/commands/calls_from/mod.rs +++ b/cli/src/commands/calls_from/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/calls_from/output.rs b/cli/src/commands/calls_from/output.rs index d0dac92..afe550b 100644 --- a/cli/src/commands/calls_from/output.rs +++ b/cli/src/commands/calls_from/output.rs @@ -1,7 +1,7 @@ //! Output formatting for calls-from command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::CallerFunction; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/calls_from/output_tests.rs b/cli/src/commands/calls_from/output_tests.rs index cd77a74..278d284 100644 --- a/cli/src/commands/calls_from/output_tests.rs +++ b/cli/src/commands/calls_from/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::CallerFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult}; + use db::types::{Call, FunctionRef, ModuleGroupResult}; use rstest::{fixture, rstest}; // ========================================================================= @@ -41,19 +41,25 @@ MyApp.Accounts (lib/my_app/accounts.ex) #[fixture] fn empty_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - "get_user".to_string(), - vec![], - ) + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: Some("get_user".to_string()), + total_items: 0, + items: vec![], + } } #[fixture] fn single_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - "get_user".to_string(), - vec![Call { + use db::types::ModuleGroup; + + let caller_func = CallerFunction { + name: "get_user".to_string(), + arity: 1, + kind: String::new(), + start_line: 10, + end_line: 15, + calls: vec![Call { caller: FunctionRef::with_definition( "MyApp.Accounts", "get_user", @@ -68,47 +74,82 @@ MyApp.Accounts (lib/my_app/accounts.ex) call_type: Some("remote".to_string()), depth: None, }], - ) + }; + + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: Some("get_user".to_string()), + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + entries: vec![caller_func], + function_count: None, + }], + } } #[fixture] fn multiple_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - String::new(), - vec![ - Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "get_user", - 1, - "", - "lib/my_app/accounts.ex", - 10, - 15, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 12, - call_type: Some("remote".to_string()), - depth: None, - }, - Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "list_users", - 0, - "", - "lib/my_app/accounts.ex", - 20, - 25, - ), - callee: FunctionRef::new("MyApp.Repo", "all", 1), - line: 22, - call_type: Some("remote".to_string()), - depth: None, - }, - ], - ) + use db::types::ModuleGroup; + + let caller_func1 = CallerFunction { + name: "get_user".to_string(), + arity: 1, + kind: String::new(), + start_line: 10, + end_line: 15, + calls: vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "get_user", + 1, + "", + "lib/my_app/accounts.ex", + 10, + 15, + ), + callee: FunctionRef::new("MyApp.Repo", "get", 2), + line: 12, + call_type: Some("remote".to_string()), + depth: None, + }], + }; + + let caller_func2 = CallerFunction { + name: "list_users".to_string(), + arity: 0, + kind: String::new(), + start_line: 20, + end_line: 25, + calls: vec![Call { + caller: FunctionRef::with_definition( + "MyApp.Accounts", + "list_users", + 0, + "", + "lib/my_app/accounts.ex", + 20, + 25, + ), + callee: FunctionRef::new("MyApp.Repo", "all", 1), + line: 22, + call_type: Some("remote".to_string()), + depth: None, + }], + }; + + ModuleGroupResult { + module_pattern: "MyApp.Accounts".to_string(), + function_pattern: None, + total_items: 2, + items: vec![ModuleGroup { + name: "MyApp.Accounts".to_string(), + file: "lib/my_app/accounts.ex".to_string(), + entries: vec![caller_func1, caller_func2], + function_count: None, + }], + } } // ========================================================================= @@ -140,7 +181,7 @@ MyApp.Accounts (lib/my_app/accounts.ex) test_name: test_format_json, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "single.json"), + expected: db::test_utils::load_output_fixture("calls_from", "single.json"), format: Json, } @@ -148,7 +189,7 @@ MyApp.Accounts (lib/my_app/accounts.ex) test_name: test_format_toon, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "single.toon"), + expected: db::test_utils::load_output_fixture("calls_from", "single.toon"), format: Toon, } @@ -156,7 +197,7 @@ MyApp.Accounts (lib/my_app/accounts.ex) test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "empty.toon"), + expected: db::test_utils::load_output_fixture("calls_from", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/calls_to/execute.rs b/cli/src/commands/calls_to/execute.rs index 866d574..10d7e03 100644 --- a/cli/src/commands/calls_to/execute.rs +++ b/cli/src/commands/calls_to/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::CallsToCmd; use crate::commands::Execute; -use crate::queries::calls_to::find_calls_to; -use crate::types::{Call, ModuleGroupResult}; +use db::queries::calls_to::find_calls_to; +use db::types::{Call, ModuleGroupResult}; use crate::utils::group_calls; /// A callee function (target) with all its callers @@ -16,48 +16,6 @@ pub struct CalleeFunction { pub callers: Vec, } -impl ModuleGroupResult { - /// Build grouped result from flat calls - pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { - let (total_items, items) = group_calls( - calls, - // Group by callee module - |call| call.callee.module.to_string(), - // Key by callee function metadata - |call| CalleeFunctionKey { - name: call.callee.name.to_string(), - arity: call.callee.arity, - }, - // Sort by caller module, name, arity, then line - |a, b| { - a.caller.module.as_ref().cmp(b.caller.module.as_ref()) - .then_with(|| a.caller.name.as_ref().cmp(b.caller.name.as_ref())) - .then_with(|| a.caller.arity.cmp(&b.caller.arity)) - .then_with(|| a.line.cmp(&b.line)) - }, - // Deduplicate by caller (module, name, arity) - |c| (c.caller.module.to_string(), c.caller.name.to_string(), c.caller.arity), - // Build CalleeFunction entry - |key, callers| CalleeFunction { - name: key.name, - arity: key.arity, - callers, - }, - // File is intentionally empty because callees are the grouping key, - // and a module can be defined across multiple files. The calls themselves - // carry file information where needed. - |_module, _map| String::new(), - ); - - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } - } -} - /// Key for grouping by callee function #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] struct CalleeFunctionKey { @@ -65,10 +23,50 @@ struct CalleeFunctionKey { arity: i64, } +/// Build grouped result from flat calls +fn build_callee_result(module_pattern: String, function_pattern: String, calls: Vec) -> ModuleGroupResult { + let (total_items, items) = group_calls( + calls, + // Group by callee module + |call| call.callee.module.to_string(), + // Key by callee function metadata + |call| CalleeFunctionKey { + name: call.callee.name.to_string(), + arity: call.callee.arity, + }, + // Sort by caller module, name, arity, then line + |a, b| { + a.caller.module.as_ref().cmp(b.caller.module.as_ref()) + .then_with(|| a.caller.name.as_ref().cmp(b.caller.name.as_ref())) + .then_with(|| a.caller.arity.cmp(&b.caller.arity)) + .then_with(|| a.line.cmp(&b.line)) + }, + // Deduplicate by caller (module, name, arity) + |c| (c.caller.module.to_string(), c.caller.name.to_string(), c.caller.arity), + // Build CalleeFunction entry + |key, callers| CalleeFunction { + name: key.name, + arity: key.arity, + callers, + }, + // File is intentionally empty because callees are the grouping key, + // and a module can be defined across multiple files. The calls themselves + // carry file information where needed. + |_module, _map| String::new(), + ); + + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, + } +} + impl Execute for CallsToCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let calls = find_calls_to( db, &self.module, @@ -79,7 +77,7 @@ impl Execute for CallsToCmd { self.common.limit, )?; - Ok(>::from_calls( + Ok(build_callee_result( self.module, self.function.unwrap_or_default(), calls, diff --git a/cli/src/commands/calls_to/mod.rs b/cli/src/commands/calls_to/mod.rs index f4d13d0..d159139 100644 --- a/cli/src/commands/calls_to/mod.rs +++ b/cli/src/commands/calls_to/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/calls_to/output.rs b/cli/src/commands/calls_to/output.rs index 2bdbc3d..de2de65 100644 --- a/cli/src/commands/calls_to/output.rs +++ b/cli/src/commands/calls_to/output.rs @@ -1,7 +1,7 @@ //! Output formatting for calls-to command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::CalleeFunction; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/calls_to/output_tests.rs b/cli/src/commands/calls_to/output_tests.rs index 9e52915..b8e3665 100644 --- a/cli/src/commands/calls_to/output_tests.rs +++ b/cli/src/commands/calls_to/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::CalleeFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult}; + use db::types::{Call, FunctionRef, ModuleGroupResult}; use rstest::{fixture, rstest}; // ========================================================================= @@ -41,19 +41,22 @@ MyApp.Repo #[fixture] fn empty_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - "get".to_string(), - vec![], - ) + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: Some("get".to_string()), + total_items: 0, + items: vec![], + } } #[fixture] fn single_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - "get".to_string(), - vec![Call { + use db::types::ModuleGroup; + + let callee_func = CalleeFunction { + name: "get".to_string(), + arity: 2, + callers: vec![Call { caller: FunctionRef::with_definition( "MyApp.Accounts", "get_user", @@ -68,15 +71,29 @@ MyApp.Repo call_type: Some("remote".to_string()), depth: None, }], - ) + }; + + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: Some("get".to_string()), + total_items: 1, + items: vec![ModuleGroup { + name: "MyApp.Repo".to_string(), + file: String::new(), + entries: vec![callee_func], + function_count: None, + }], + } } #[fixture] fn multiple_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - String::new(), - vec![ + use db::types::ModuleGroup; + + let callee_func = CalleeFunction { + name: "get".to_string(), + arity: 2, + callers: vec![ Call { caller: FunctionRef::with_definition( "MyApp.Accounts", @@ -108,7 +125,19 @@ MyApp.Repo depth: None, }, ], - ) + }; + + ModuleGroupResult { + module_pattern: "MyApp.Repo".to_string(), + function_pattern: None, + total_items: 2, + items: vec![ModuleGroup { + name: "MyApp.Repo".to_string(), + file: String::new(), + entries: vec![callee_func], + function_count: None, + }], + } } // ========================================================================= @@ -140,7 +169,7 @@ MyApp.Repo test_name: test_format_json, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "single.json"), + expected: db::test_utils::load_output_fixture("calls_to", "single.json"), format: Json, } @@ -148,7 +177,7 @@ MyApp.Repo test_name: test_format_toon, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "single.toon"), + expected: db::test_utils::load_output_fixture("calls_to", "single.toon"), format: Toon, } @@ -156,7 +185,7 @@ MyApp.Repo test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "empty.toon"), + expected: db::test_utils::load_output_fixture("calls_to", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/clusters/execute.rs b/cli/src/commands/clusters/execute.rs index 76ddd29..cfe3f0a 100644 --- a/cli/src/commands/clusters/execute.rs +++ b/cli/src/commands/clusters/execute.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::ClustersCmd; use crate::commands::Execute; -use crate::queries::clusters::get_module_calls; +use db::queries::clusters::get_module_calls; /// A single namespace cluster #[derive(Debug, Clone, Serialize)] @@ -44,7 +44,7 @@ pub struct ClustersResult { impl Execute for ClustersCmd { type Output = ClustersResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { // Get all inter-module calls let calls = get_module_calls(db, &self.common.project)?; diff --git a/cli/src/commands/clusters/mod.rs b/cli/src/commands/clusters/mod.rs index 0c4e1e9..a08a3ea 100644 --- a/cli/src/commands/clusters/mod.rs +++ b/cli/src/commands/clusters/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/complexity/execute.rs b/cli/src/commands/complexity/execute.rs index 105742b..e625e30 100644 --- a/cli/src/commands/complexity/execute.rs +++ b/cli/src/commands/complexity/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::ComplexityCmd; use crate::commands::Execute; -use crate::queries::complexity::find_complexity_metrics; -use crate::types::ModuleCollectionResult; +use db::queries::complexity::find_complexity_metrics; +use db::types::ModuleCollectionResult; /// A single complexity metric entry #[derive(Debug, Clone, Serialize)] @@ -21,7 +21,7 @@ pub struct ComplexityEntry { impl Execute for ComplexityCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let metrics = find_complexity_metrics( db, self.min, diff --git a/cli/src/commands/complexity/mod.rs b/cli/src/commands/complexity/mod.rs index d8e7d23..9c9a7eb 100644 --- a/cli/src/commands/complexity/mod.rs +++ b/cli/src/commands/complexity/mod.rs @@ -11,7 +11,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/complexity/output.rs b/cli/src/commands/complexity/output.rs index 0acc4dc..1aa9eea 100644 --- a/cli/src/commands/complexity/output.rs +++ b/cli/src/commands/complexity/output.rs @@ -2,7 +2,7 @@ use super::execute::ComplexityEntry; use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; impl TableFormatter for ModuleCollectionResult { type Entry = ComplexityEntry; diff --git a/cli/src/commands/complexity/output_tests.rs b/cli/src/commands/complexity/output_tests.rs index 47b6d01..87296a0 100644 --- a/cli/src/commands/complexity/output_tests.rs +++ b/cli/src/commands/complexity/output_tests.rs @@ -4,7 +4,7 @@ mod tests { use super::super::execute::ComplexityEntry; use crate::output::Outputable; - use crate::types::{ModuleCollectionResult, ModuleGroup}; + use db::types::{ModuleCollectionResult, ModuleGroup}; #[test] fn test_format_table_single_function() { diff --git a/cli/src/commands/cycles/execute.rs b/cli/src/commands/cycles/execute.rs index 9eb497c..b0d5a15 100644 --- a/cli/src/commands/cycles/execute.rs +++ b/cli/src/commands/cycles/execute.rs @@ -7,7 +7,7 @@ use serde::Serialize; use super::CyclesCmd; use crate::commands::Execute; -use crate::queries::cycles::find_cycle_edges; +use db::queries::cycles::find_cycle_edges; /// A single cycle found in the module dependency graph #[derive(Debug, Clone, Serialize)] @@ -32,7 +32,7 @@ pub struct CyclesResult { impl Execute for CyclesCmd { type Output = CyclesResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { // Get cycle edges from the database let edges = find_cycle_edges( db, diff --git a/cli/src/commands/cycles/mod.rs b/cli/src/commands/cycles/mod.rs index c1b96c7..e9ff284 100644 --- a/cli/src/commands/cycles/mod.rs +++ b/cli/src/commands/cycles/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/depended_by/execute.rs b/cli/src/commands/depended_by/execute.rs index ccb45ab..765bc03 100644 --- a/cli/src/commands/depended_by/execute.rs +++ b/cli/src/commands/depended_by/execute.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::DependedByCmd; use crate::commands::Execute; -use crate::queries::depended_by::find_dependents; -use crate::types::{Call, ModuleGroupResult, ModuleGroup}; +use db::queries::depended_by::find_dependents; +use db::types::{Call, ModuleGroupResult, ModuleGroup}; /// A target function being called in the dependency module #[derive(Debug, Clone, Serialize)] @@ -28,92 +28,90 @@ pub struct DependentCaller { pub targets: Vec, } -impl ModuleGroupResult { - /// Build a grouped structure from flat calls - pub fn from_calls(target_module: String, calls: Vec) -> Self { - let total_items = calls.len(); - - if calls.is_empty() { - return ModuleGroupResult { - module_pattern: target_module, - function_pattern: None, - total_items: 0, - items: vec![], - }; - } - - // Group by caller_module -> caller_function -> targets - // Using BTreeMap for automatic sorting by module and function key - let mut by_module: BTreeMap>> = BTreeMap::new(); - for call in &calls { - by_module - .entry(call.caller.module.to_string()) - .or_default() - .entry((call.caller.name.to_string(), call.caller.arity)) - .or_default() - .push(call); - } - - let items: Vec> = by_module - .into_iter() - .map(|(module_name, callers_map)| { - // Determine module file from first caller in first function - let module_file = callers_map - .values() - .next() - .and_then(|calls| calls.first()) - .and_then(|call| call.caller.file.as_deref()) - .unwrap_or("") - .to_string(); - - let entries: Vec = callers_map - .into_iter() - .map(|((func_name, arity), func_calls)| { - let first = func_calls[0]; - - let targets: Vec = func_calls - .iter() - .map(|c| DependentTarget { - function: c.callee.name.to_string(), - arity: c.callee.arity, - line: c.line, - }) - .collect(); - - DependentCaller { - function: func_name, - arity, - kind: first.caller.kind.as_deref().unwrap_or("").to_string(), - start_line: first.caller.start_line.unwrap_or(0), - end_line: first.caller.end_line.unwrap_or(0), - file: first.caller.file.as_deref().unwrap_or("").to_string(), - targets, - } - }) - .collect(); - - ModuleGroup { - name: module_name, - file: module_file, - entries, - function_count: None, - } - }) - .collect(); - - ModuleGroupResult { +/// Build a grouped structure from flat calls +fn build_dependent_caller_result(target_module: String, calls: Vec) -> ModuleGroupResult { + let total_items = calls.len(); + + if calls.is_empty() { + return ModuleGroupResult { module_pattern: target_module, function_pattern: None, - total_items, - items, - } + total_items: 0, + items: vec![], + }; + } + + // Group by caller_module -> caller_function -> targets + // Using BTreeMap for automatic sorting by module and function key + let mut by_module: BTreeMap>> = BTreeMap::new(); + for call in &calls { + by_module + .entry(call.caller.module.to_string()) + .or_default() + .entry((call.caller.name.to_string(), call.caller.arity)) + .or_default() + .push(call); + } + + let items: Vec> = by_module + .into_iter() + .map(|(module_name, callers_map)| { + // Determine module file from first caller in first function + let module_file = callers_map + .values() + .next() + .and_then(|calls| calls.first()) + .and_then(|call| call.caller.file.as_deref()) + .unwrap_or("") + .to_string(); + + let entries: Vec = callers_map + .into_iter() + .map(|((func_name, arity), func_calls)| { + let first = func_calls[0]; + + let targets: Vec = func_calls + .iter() + .map(|c| DependentTarget { + function: c.callee.name.to_string(), + arity: c.callee.arity, + line: c.line, + }) + .collect(); + + DependentCaller { + function: func_name, + arity, + kind: first.caller.kind.as_deref().unwrap_or("").to_string(), + start_line: first.caller.start_line.unwrap_or(0), + end_line: first.caller.end_line.unwrap_or(0), + file: first.caller.file.as_deref().unwrap_or("").to_string(), + targets, + } + }) + .collect(); + + ModuleGroup { + name: module_name, + file: module_file, + entries, + function_count: None, + } + }) + .collect(); + + ModuleGroupResult { + module_pattern: target_module, + function_pattern: None, + total_items, + items, } } impl Execute for DependedByCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let calls = find_dependents( db, &self.module, @@ -122,6 +120,6 @@ impl Execute for DependedByCmd { self.common.limit, )?; - Ok(>::from_calls(self.module, calls)) + Ok(build_dependent_caller_result(self.module, calls)) } } diff --git a/cli/src/commands/depended_by/mod.rs b/cli/src/commands/depended_by/mod.rs index d52f684..3dcc2ce 100644 --- a/cli/src/commands/depended_by/mod.rs +++ b/cli/src/commands/depended_by/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/depended_by/output.rs b/cli/src/commands/depended_by/output.rs index abb7081..0949fb3 100644 --- a/cli/src/commands/depended_by/output.rs +++ b/cli/src/commands/depended_by/output.rs @@ -1,7 +1,7 @@ //! Output formatting for depended-by command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::DependentCaller; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/depended_by/output_tests.rs b/cli/src/commands/depended_by/output_tests.rs index d1a27d7..a595efa 100644 --- a/cli/src/commands/depended_by/output_tests.rs +++ b/cli/src/commands/depended_by/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::{DependentCaller, DependentTarget}; - use crate::types::{ModuleGroupResult, ModuleGroup}; + use db::types::{ModuleGroupResult, ModuleGroup}; use rstest::{fixture, rstest}; // ========================================================================= @@ -154,7 +154,7 @@ MyApp.Service: test_name: test_format_json, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "single.json"), + expected: db::test_utils::load_output_fixture("depended_by", "single.json"), format: Json, } @@ -162,7 +162,7 @@ MyApp.Service: test_name: test_format_toon, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "single.toon"), + expected: db::test_utils::load_output_fixture("depended_by", "single.toon"), format: Toon, } @@ -170,7 +170,7 @@ MyApp.Service: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "empty.toon"), + expected: db::test_utils::load_output_fixture("depended_by", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/depends_on/execute.rs b/cli/src/commands/depends_on/execute.rs index a645581..a5c3223 100644 --- a/cli/src/commands/depends_on/execute.rs +++ b/cli/src/commands/depends_on/execute.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::DependsOnCmd; use crate::commands::Execute; -use crate::queries::depends_on::find_dependencies; -use crate::types::{Call, ModuleGroupResult}; +use db::queries::depends_on::find_dependencies; +use db::types::{Call, ModuleGroupResult}; use crate::utils::convert_to_module_groups; /// A function in a dependency module being called @@ -17,59 +17,57 @@ pub struct DependencyFunction { pub callers: Vec, } -impl ModuleGroupResult { - /// Build a grouped structure from flat calls - pub fn from_calls(source_module: String, calls: Vec) -> Self { - let total_items = calls.len(); +/// Build a grouped structure from flat calls +fn build_dependency_result(source_module: String, calls: Vec) -> ModuleGroupResult { + let total_items = calls.len(); - if calls.is_empty() { - return ModuleGroupResult { - module_pattern: source_module, - function_pattern: None, - total_items: 0, - items: vec![], - }; - } + if calls.is_empty() { + return ModuleGroupResult { + module_pattern: source_module, + function_pattern: None, + total_items: 0, + items: vec![], + }; + } - // Group by callee_module -> callee_function -> callers - // Using BTreeMap for automatic sorting - let mut by_module: BTreeMap>> = BTreeMap::new(); - for call in calls { - by_module - .entry(call.callee.module.to_string()) - .or_default() - .entry((call.callee.name.to_string(), call.callee.arity)) - .or_default() - .push(call); - } + // Group by callee_module -> callee_function -> callers + // Using BTreeMap for automatic sorting + let mut by_module: BTreeMap>> = BTreeMap::new(); + for call in calls { + by_module + .entry(call.callee.module.to_string()) + .or_default() + .entry((call.callee.name.to_string(), call.callee.arity)) + .or_default() + .push(call); + } - // Convert to ModuleGroup structure - let items = convert_to_module_groups( - by_module, - |(func_name, arity), callers| DependencyFunction { - name: func_name, - arity, - callers, - }, - // File is intentionally empty because dependencies are the grouping key, - // and a module can depend on functions defined across multiple files. - // The dependency targets themselves carry file information where needed. - |_module, _map| String::new(), - ); + // Convert to ModuleGroup structure + let items = convert_to_module_groups( + by_module, + |(func_name, arity), callers| DependencyFunction { + name: func_name, + arity, + callers, + }, + // File is intentionally empty because dependencies are the grouping key, + // and a module can depend on functions defined across multiple files. + // The dependency targets themselves carry file information where needed. + |_module, _map| String::new(), + ); - ModuleGroupResult { - module_pattern: source_module, - function_pattern: None, - total_items, - items, - } + ModuleGroupResult { + module_pattern: source_module, + function_pattern: None, + total_items, + items, } } impl Execute for DependsOnCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let calls = find_dependencies( db, &self.module, @@ -78,6 +76,6 @@ impl Execute for DependsOnCmd { self.common.limit, )?; - Ok(>::from_calls(self.module, calls)) + Ok(build_dependency_result(self.module, calls)) } } diff --git a/cli/src/commands/depends_on/mod.rs b/cli/src/commands/depends_on/mod.rs index ea72d6b..2724678 100644 --- a/cli/src/commands/depends_on/mod.rs +++ b/cli/src/commands/depends_on/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/depends_on/output.rs b/cli/src/commands/depends_on/output.rs index 784e713..af61563 100644 --- a/cli/src/commands/depends_on/output.rs +++ b/cli/src/commands/depends_on/output.rs @@ -1,7 +1,7 @@ //! Output formatting for depends-on command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::DependencyFunction; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/depends_on/output_tests.rs b/cli/src/commands/depends_on/output_tests.rs index 7c74549..006e8a2 100644 --- a/cli/src/commands/depends_on/output_tests.rs +++ b/cli/src/commands/depends_on/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::DependencyFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult, ModuleGroup}; + use db::types::{Call, FunctionRef, ModuleGroupResult, ModuleGroup}; use rstest::{fixture, rstest}; // ========================================================================= @@ -172,7 +172,7 @@ Phoenix.View: test_name: test_format_json, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "single.json"), + expected: db::test_utils::load_output_fixture("depends_on", "single.json"), format: Json, } @@ -180,7 +180,7 @@ Phoenix.View: test_name: test_format_toon, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "single.toon"), + expected: db::test_utils::load_output_fixture("depends_on", "single.toon"), format: Toon, } @@ -188,7 +188,7 @@ Phoenix.View: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "empty.toon"), + expected: db::test_utils::load_output_fixture("depends_on", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/describe/execute.rs b/cli/src/commands/describe/execute.rs index 2e2db5a..4b45b7f 100644 --- a/cli/src/commands/describe/execute.rs +++ b/cli/src/commands/describe/execute.rs @@ -34,7 +34,7 @@ pub struct DescribeResult { impl Execute for DescribeCmd { type Output = DescribeResult; - fn execute(self, _db: &cozo::DbInstance) -> Result> { + fn execute(self, _db: &db::DbInstance) -> Result> { if self.commands.is_empty() { // List all commands grouped by category let categories_map = descriptions_by_category(); diff --git a/cli/src/commands/describe/mod.rs b/cli/src/commands/describe/mod.rs index f80a258..18e1fa1 100644 --- a/cli/src/commands/describe/mod.rs +++ b/cli/src/commands/describe/mod.rs @@ -5,7 +5,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/duplicates/execute.rs b/cli/src/commands/duplicates/execute.rs index 8428e2a..e6a5563 100644 --- a/cli/src/commands/duplicates/execute.rs +++ b/cli/src/commands/duplicates/execute.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::DuplicatesCmd; use crate::commands::Execute; -use crate::queries::duplicates::find_duplicates; +use db::queries::duplicates::find_duplicates; // ============================================================================= // Detailed mode types (default) @@ -83,7 +83,7 @@ pub enum DuplicatesOutput { impl Execute for DuplicatesCmd { type Output = DuplicatesOutput; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let functions = find_duplicates( db, &self.common.project, @@ -102,7 +102,7 @@ impl Execute for DuplicatesCmd { } fn build_detailed_result( - functions: Vec, + functions: Vec, ) -> DuplicatesResult { // Group by hash let mut groups_map: BTreeMap> = BTreeMap::new(); @@ -134,7 +134,7 @@ fn build_detailed_result( } fn build_by_module_result( - functions: Vec, + functions: Vec, ) -> DuplicatesByModuleResult { // Group by module first let mut module_map: BTreeMap> = BTreeMap::new(); diff --git a/cli/src/commands/duplicates/mod.rs b/cli/src/commands/duplicates/mod.rs index 08940b7..d4caa85 100644 --- a/cli/src/commands/duplicates/mod.rs +++ b/cli/src/commands/duplicates/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/function/execute.rs b/cli/src/commands/function/execute.rs index f14fdbb..352916b 100644 --- a/cli/src/commands/function/execute.rs +++ b/cli/src/commands/function/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::FunctionCmd; use crate::commands::Execute; -use crate::queries::function::{find_functions, FunctionSignature}; -use crate::types::ModuleGroupResult; +use db::queries::function::{find_functions, FunctionSignature}; +use db::types::ModuleGroupResult; /// A function signature within a module #[derive(Debug, Clone, Serialize)] @@ -18,42 +18,40 @@ pub struct FuncSig { pub return_type: String, } -impl ModuleGroupResult { - /// Build grouped result from flat FunctionSignature list - fn from_signatures( - module_pattern: String, - function_pattern: String, - signatures: Vec, - ) -> Self { - let total_items = signatures.len(); +/// Build grouped result from flat FunctionSignature list +fn build_function_signatures_result( + module_pattern: String, + function_pattern: String, + signatures: Vec, +) -> ModuleGroupResult { + let total_items = signatures.len(); - // Use helper to group by module - let items = crate::utils::group_by_module(signatures, |sig| { - let func_sig = FuncSig { - name: sig.name, - arity: sig.arity, - args: sig.args, - return_type: sig.return_type, - }; - // File is intentionally empty for functions because the function command - // queries the functions table which doesn't track file locations. - // File locations are available in function_locations table if needed. - (sig.module, func_sig) - }); + // Use helper to group by module + let items = crate::utils::group_by_module(signatures, |sig| { + let func_sig = FuncSig { + name: sig.name, + arity: sig.arity, + args: sig.args, + return_type: sig.return_type, + }; + // File is intentionally empty for functions because the function command + // queries the functions table which doesn't track file locations. + // File locations are available in function_locations table if needed. + (sig.module, func_sig) + }); - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } + ModuleGroupResult { + module_pattern, + function_pattern: Some(function_pattern), + total_items, + items, } } impl Execute for FunctionCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let signatures = find_functions( db, &self.module, @@ -64,7 +62,7 @@ impl Execute for FunctionCmd { self.common.limit, )?; - Ok(>::from_signatures( + Ok(build_function_signatures_result( self.module, self.function, signatures, diff --git a/cli/src/commands/function/mod.rs b/cli/src/commands/function/mod.rs index a2b21e5..632008c 100644 --- a/cli/src/commands/function/mod.rs +++ b/cli/src/commands/function/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/function/output.rs b/cli/src/commands/function/output.rs index dffa742..76dbeab 100644 --- a/cli/src/commands/function/output.rs +++ b/cli/src/commands/function/output.rs @@ -1,7 +1,7 @@ //! Output formatting for function command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::FuncSig; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/function/output_tests.rs b/cli/src/commands/function/output_tests.rs index 86aec7f..a6b5f81 100644 --- a/cli/src/commands/function/output_tests.rs +++ b/cli/src/commands/function/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::FuncSig; - use crate::types::{ModuleGroupResult, ModuleGroup}; + use db::types::{ModuleGroupResult, ModuleGroup}; use rstest::{fixture, rstest}; // ========================================================================= @@ -130,7 +130,7 @@ MyApp.Accounts: test_name: test_format_json, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "single.json"), + expected: db::test_utils::load_output_fixture("function", "single.json"), format: Json, } @@ -138,7 +138,7 @@ MyApp.Accounts: test_name: test_format_toon, fixture: single_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "single.toon"), + expected: db::test_utils::load_output_fixture("function", "single.toon"), format: Toon, } @@ -146,7 +146,7 @@ MyApp.Accounts: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "empty.toon"), + expected: db::test_utils::load_output_fixture("function", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/god_modules/execute.rs b/cli/src/commands/god_modules/execute.rs index cf4ee0d..f3ca9e7 100644 --- a/cli/src/commands/god_modules/execute.rs +++ b/cli/src/commands/god_modules/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::GodModulesCmd; use crate::commands::Execute; -use crate::queries::hotspots::{find_hotspots, get_function_counts, get_module_loc, HotspotKind}; -use crate::types::{ModuleCollectionResult, ModuleGroup}; +use db::queries::hotspots::{find_hotspots, get_function_counts, get_module_loc, HotspotKind}; +use db::types::{ModuleCollectionResult, ModuleGroup}; /// A single god module entry #[derive(Debug, Clone, Serialize)] @@ -20,7 +20,7 @@ pub struct GodModuleEntry { impl Execute for GodModulesCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { // Get function counts for all modules let func_counts = get_function_counts( db, diff --git a/cli/src/commands/god_modules/mod.rs b/cli/src/commands/god_modules/mod.rs index 809b4f6..b62914e 100644 --- a/cli/src/commands/god_modules/mod.rs +++ b/cli/src/commands/god_modules/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/god_modules/output.rs b/cli/src/commands/god_modules/output.rs index 678d811..5a6c65e 100644 --- a/cli/src/commands/god_modules/output.rs +++ b/cli/src/commands/god_modules/output.rs @@ -2,7 +2,7 @@ use super::execute::GodModuleEntry; use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; impl TableFormatter for ModuleCollectionResult { type Entry = GodModuleEntry; diff --git a/cli/src/commands/hotspots/cli_tests.rs b/cli/src/commands/hotspots/cli_tests.rs index 6ff3c65..0ca8f1e 100644 --- a/cli/src/commands/hotspots/cli_tests.rs +++ b/cli/src/commands/hotspots/cli_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use crate::cli::Args; - use crate::queries::hotspots::HotspotKind; + use db::queries::hotspots::HotspotKind; use clap::Parser; use rstest::rstest; diff --git a/cli/src/commands/hotspots/execute.rs b/cli/src/commands/hotspots/execute.rs index 5d8ca38..bafb3cb 100644 --- a/cli/src/commands/hotspots/execute.rs +++ b/cli/src/commands/hotspots/execute.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::HotspotsCmd; use crate::commands::Execute; use crate::output::Outputable; -use crate::queries::hotspots::find_hotspots; +use db::queries::hotspots::find_hotspots; /// A function hotspot entry #[derive(Debug, Clone, Serialize)] @@ -100,7 +100,7 @@ impl Outputable for HotspotsResult { impl Execute for HotspotsCmd { type Output = HotspotsResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let hotspots = find_hotspots( db, self.kind, @@ -113,10 +113,10 @@ impl Execute for HotspotsCmd { )?; let kind_str = match self.kind { - crate::queries::hotspots::HotspotKind::Incoming => "incoming", - crate::queries::hotspots::HotspotKind::Outgoing => "outgoing", - crate::queries::hotspots::HotspotKind::Total => "total", - crate::queries::hotspots::HotspotKind::Ratio => "ratio", + db::queries::hotspots::HotspotKind::Incoming => "incoming", + db::queries::hotspots::HotspotKind::Outgoing => "outgoing", + db::queries::hotspots::HotspotKind::Total => "total", + db::queries::hotspots::HotspotKind::Ratio => "ratio", }; let entries: Vec = hotspots diff --git a/cli/src/commands/hotspots/execute_tests.rs b/cli/src/commands/hotspots/execute_tests.rs index 38af50b..ae25895 100644 --- a/cli/src/commands/hotspots/execute_tests.rs +++ b/cli/src/commands/hotspots/execute_tests.rs @@ -5,7 +5,7 @@ mod tests { use super::super::HotspotsCmd; use crate::commands::CommonArgs; use crate::commands::Execute; - use crate::queries::hotspots::HotspotKind; + use db::queries::hotspots::HotspotKind; use rstest::{fixture, rstest}; crate::shared_fixture! { @@ -19,7 +19,7 @@ mod tests { // ========================================================================= #[rstest] - fn test_hotspots_incoming(populated_db: cozo::DbInstance) { + fn test_hotspots_incoming(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Incoming, @@ -37,7 +37,7 @@ mod tests { } #[rstest] - fn test_hotspots_outgoing(populated_db: cozo::DbInstance) { + fn test_hotspots_outgoing(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Outgoing, @@ -55,7 +55,7 @@ mod tests { } #[rstest] - fn test_hotspots_total(populated_db: cozo::DbInstance) { + fn test_hotspots_total(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Total, @@ -73,7 +73,7 @@ mod tests { } #[rstest] - fn test_hotspots_ratio(populated_db: cozo::DbInstance) { + fn test_hotspots_ratio(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Ratio, @@ -97,7 +97,7 @@ mod tests { // ========================================================================= #[rstest] - fn test_hotspots_with_module_filter(populated_db: cozo::DbInstance) { + fn test_hotspots_with_module_filter(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: Some("Accounts".to_string()), kind: HotspotKind::Incoming, @@ -115,7 +115,7 @@ mod tests { } #[rstest] - fn test_hotspots_with_limit(populated_db: cozo::DbInstance) { + fn test_hotspots_with_limit(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Incoming, @@ -132,7 +132,7 @@ mod tests { } #[rstest] - fn test_hotspots_exclude_generated(populated_db: cozo::DbInstance) { + fn test_hotspots_exclude_generated(populated_db: db::DbInstance) { let cmd = HotspotsCmd { module: None, kind: HotspotKind::Incoming, diff --git a/cli/src/commands/hotspots/mod.rs b/cli/src/commands/hotspots/mod.rs index 7dc4ad7..19d095c 100644 --- a/cli/src/commands/hotspots/mod.rs +++ b/cli/src/commands/hotspots/mod.rs @@ -7,11 +7,11 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; -use crate::queries::hotspots::HotspotKind; +use db::queries::hotspots::HotspotKind; /// Find functions with the most incoming/outgoing calls #[derive(Args, Debug)] diff --git a/cli/src/commands/import/execute.rs b/cli/src/commands/import/execute.rs index 2bfe0dd..c4794c7 100644 --- a/cli/src/commands/import/execute.rs +++ b/cli/src/commands/import/execute.rs @@ -1,12 +1,12 @@ use std::error::Error; use std::fs; -use cozo::DbInstance; +use db::DbInstance; use super::ImportCmd; use crate::commands::Execute; -use crate::queries::import::{clear_project_data, import_graph, ImportError, ImportResult}; -use crate::queries::import_models::CallGraph; +use db::queries::import::{clear_project_data, import_graph, ImportError, ImportResult}; +use db::queries::import_models::CallGraph; impl Execute for ImportCmd { type Output = ImportResult; @@ -39,7 +39,7 @@ impl Execute for ImportCmd { #[cfg(test)] mod tests { use super::*; - use crate::db::open_db; + use db::open_db; use rstest::{fixture, rstest}; use std::io::Write; use tempfile::NamedTempFile; diff --git a/cli/src/commands/import/mod.rs b/cli/src/commands/import/mod.rs index 75d43c6..df7209a 100644 --- a/cli/src/commands/import/mod.rs +++ b/cli/src/commands/import/mod.rs @@ -7,7 +7,7 @@ use std::error::Error; use std::path::PathBuf; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/import/output.rs b/cli/src/commands/import/output.rs index 1ab6ed4..4789965 100644 --- a/cli/src/commands/import/output.rs +++ b/cli/src/commands/import/output.rs @@ -1,7 +1,7 @@ //! Output formatting for import command results. use crate::output::Outputable; -use crate::queries::import::ImportResult; +use db::queries::import::ImportResult; impl Outputable for ImportResult { fn to_table(&self) -> String { diff --git a/cli/src/commands/import/output_tests.rs b/cli/src/commands/import/output_tests.rs index f40f0db..38ed595 100644 --- a/cli/src/commands/import/output_tests.rs +++ b/cli/src/commands/import/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use crate::output::OutputFormat; - use crate::queries::import::{ImportResult, SchemaResult}; + use db::queries::import::{ImportResult, SchemaResult}; use rstest::{fixture, rstest}; const EMPTY_TABLE_OUTPUT: &str = "\ @@ -99,7 +99,7 @@ Created Schemas: test_name: test_format_json, fixture: full_result, fixture_type: ImportResult, - expected: crate::test_utils::load_output_fixture("import", "full.json"), + expected: db::test_utils::load_output_fixture("import", "full.json"), format: Json, } @@ -107,7 +107,7 @@ Created Schemas: test_name: test_format_toon, fixture: full_result, fixture_type: ImportResult, - expected: crate::test_utils::load_output_fixture("import", "full.toon"), + expected: db::test_utils::load_output_fixture("import", "full.toon"), format: Toon, } diff --git a/cli/src/commands/large_functions/execute.rs b/cli/src/commands/large_functions/execute.rs index 576fcfd..088e08a 100644 --- a/cli/src/commands/large_functions/execute.rs +++ b/cli/src/commands/large_functions/execute.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::LargeFunctionsCmd; use crate::commands::Execute; -use crate::queries::large_functions::find_large_functions; -use crate::types::{ModuleCollectionResult, ModuleGroup}; +use db::queries::large_functions::find_large_functions; +use db::types::{ModuleCollectionResult, ModuleGroup}; /// A single large function entry #[derive(Debug, Clone, Serialize)] @@ -22,7 +22,7 @@ pub struct LargeFunctionEntry { impl Execute for LargeFunctionsCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let large_functions = find_large_functions( db, self.min_lines, diff --git a/cli/src/commands/large_functions/mod.rs b/cli/src/commands/large_functions/mod.rs index 245fead..fdd70b2 100644 --- a/cli/src/commands/large_functions/mod.rs +++ b/cli/src/commands/large_functions/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/large_functions/output.rs b/cli/src/commands/large_functions/output.rs index f133de2..838930a 100644 --- a/cli/src/commands/large_functions/output.rs +++ b/cli/src/commands/large_functions/output.rs @@ -2,7 +2,7 @@ use super::execute::LargeFunctionEntry; use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; impl TableFormatter for ModuleCollectionResult { type Entry = LargeFunctionEntry; diff --git a/cli/src/commands/location/execute.rs b/cli/src/commands/location/execute.rs index fd1c6d6..8fed344 100644 --- a/cli/src/commands/location/execute.rs +++ b/cli/src/commands/location/execute.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::LocationCmd; use crate::commands::Execute; -use crate::queries::location::{find_locations, FunctionLocation}; +use db::queries::location::{find_locations, FunctionLocation}; /// A single clause (definition) of a function #[derive(Debug, Clone, Serialize)] @@ -111,7 +111,7 @@ impl LocationResult { impl Execute for LocationCmd { type Output = LocationResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let locations = find_locations( db, self.module.as_deref(), diff --git a/cli/src/commands/location/mod.rs b/cli/src/commands/location/mod.rs index b4b016e..49cb323 100644 --- a/cli/src/commands/location/mod.rs +++ b/cli/src/commands/location/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/location/output_tests.rs b/cli/src/commands/location/output_tests.rs index 2c7f752..e0c5d48 100644 --- a/cli/src/commands/location/output_tests.rs +++ b/cli/src/commands/location/output_tests.rs @@ -147,7 +147,7 @@ MyApp.Users: test_name: test_format_json, fixture: single_result, fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "single.json"), + expected: db::test_utils::load_output_fixture("location", "single.json"), format: Json, } @@ -155,7 +155,7 @@ MyApp.Users: test_name: test_format_toon, fixture: single_result, fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "single.toon"), + expected: db::test_utils::load_output_fixture("location", "single.toon"), format: Toon, } @@ -163,7 +163,7 @@ MyApp.Users: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "empty.toon"), + expected: db::test_utils::load_output_fixture("location", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/many_clauses/execute.rs b/cli/src/commands/many_clauses/execute.rs index 32d8757..f8003a4 100644 --- a/cli/src/commands/many_clauses/execute.rs +++ b/cli/src/commands/many_clauses/execute.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::ManyClausesCmd; use crate::commands::Execute; -use crate::queries::many_clauses::find_many_clauses; -use crate::types::{ModuleCollectionResult, ModuleGroup}; +use db::queries::many_clauses::find_many_clauses; +use db::types::{ModuleCollectionResult, ModuleGroup}; /// A single function with many clauses entry #[derive(Debug, Clone, Serialize)] @@ -22,7 +22,7 @@ pub struct ManyClausesEntry { impl Execute for ManyClausesCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let many_clauses = find_many_clauses( db, self.min_clauses, diff --git a/cli/src/commands/many_clauses/mod.rs b/cli/src/commands/many_clauses/mod.rs index 3195bc2..d812501 100644 --- a/cli/src/commands/many_clauses/mod.rs +++ b/cli/src/commands/many_clauses/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/many_clauses/output.rs b/cli/src/commands/many_clauses/output.rs index 32b9a33..40831a4 100644 --- a/cli/src/commands/many_clauses/output.rs +++ b/cli/src/commands/many_clauses/output.rs @@ -2,7 +2,7 @@ use super::execute::ManyClausesEntry; use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; impl TableFormatter for ModuleCollectionResult { type Entry = ManyClausesEntry; diff --git a/cli/src/commands/mod.rs b/cli/src/commands/mod.rs index eac19b7..d17418b 100644 --- a/cli/src/commands/mod.rs +++ b/cli/src/commands/mod.rs @@ -91,7 +91,7 @@ use clap::Subcommand; use enum_dispatch::enum_dispatch; use std::error::Error; -use cozo::DbInstance; +use db::DbInstance; use crate::output::{OutputFormat, Outputable}; @@ -99,7 +99,7 @@ use crate::output::{OutputFormat, Outputable}; pub trait Execute { type Output: Outputable; - fn execute(self, db: &DbInstance) -> Result>; + fn execute(self, db: &db::DbInstance) -> Result>; } /// Trait for commands that can be executed and formatted. diff --git a/cli/src/commands/path/execute.rs b/cli/src/commands/path/execute.rs index 2dee335..100cdbf 100644 --- a/cli/src/commands/path/execute.rs +++ b/cli/src/commands/path/execute.rs @@ -4,7 +4,7 @@ use serde::Serialize; use super::PathCmd; use crate::commands::Execute; -use crate::queries::path::{find_paths, CallPath}; +use db::queries::path::{find_paths, CallPath}; /// Result of the path command execution #[derive(Debug, Default, Serialize)] @@ -20,7 +20,7 @@ pub struct PathResult { impl Execute for PathCmd { type Output = PathResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let mut result = PathResult { from_module: self.from_module.clone(), from_function: self.from_function.clone(), diff --git a/cli/src/commands/path/mod.rs b/cli/src/commands/path/mod.rs index 75d4f25..67ab3c7 100644 --- a/cli/src/commands/path/mod.rs +++ b/cli/src/commands/path/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/path/output_tests.rs b/cli/src/commands/path/output_tests.rs index 1fe1805..c520666 100644 --- a/cli/src/commands/path/output_tests.rs +++ b/cli/src/commands/path/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::PathResult; - use crate::queries::path::{CallPath, PathStep}; + use db::queries::path::{CallPath, PathStep}; use rstest::{fixture, rstest}; // ========================================================================= @@ -100,7 +100,7 @@ Path 1: test_name: test_format_json, fixture: single_path_result, fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "single.json"), + expected: db::test_utils::load_output_fixture("path", "single.json"), format: Json, } @@ -108,7 +108,7 @@ Path 1: test_name: test_format_toon, fixture: single_path_result, fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "single.toon"), + expected: db::test_utils::load_output_fixture("path", "single.toon"), format: Toon, } @@ -116,7 +116,7 @@ Path 1: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "empty.toon"), + expected: db::test_utils::load_output_fixture("path", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/returns/execute.rs b/cli/src/commands/returns/execute.rs index 20eeeac..0cfbe85 100644 --- a/cli/src/commands/returns/execute.rs +++ b/cli/src/commands/returns/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::ReturnsCmd; use crate::commands::Execute; -use crate::queries::returns::{find_returns, ReturnEntry}; -use crate::types::ModuleGroupResult; +use db::queries::returns::{find_returns, ReturnEntry}; +use db::types::ModuleGroupResult; /// A function's return type information #[derive(Debug, Clone, Serialize)] @@ -16,39 +16,37 @@ pub struct ReturnInfo { pub line: i64, } -impl ModuleGroupResult { - /// Build grouped result from flat ReturnEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); +/// Build grouped result from flat ReturnEntry list +fn build_return_info_result( + pattern: String, + module_filter: Option, + entries: Vec, +) -> ModuleGroupResult { + let total_items = entries.len(); - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let return_info = ReturnInfo { - name: entry.name, - arity: entry.arity, - return_type: entry.return_string, - line: entry.line, - }; - (entry.module, return_info) - }); + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let return_info = ReturnInfo { + name: entry.name, + arity: entry.arity, + return_type: entry.return_string, + line: entry.line, + }; + (entry.module, return_info) + }); - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, } } impl Execute for ReturnsCmd { type Output = ModuleGroupResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let entries = find_returns( db, &self.pattern, @@ -58,7 +56,7 @@ impl Execute for ReturnsCmd { self.common.limit, )?; - Ok(>::from_entries( + Ok(build_return_info_result( self.pattern, self.module, entries, diff --git a/cli/src/commands/returns/mod.rs b/cli/src/commands/returns/mod.rs index 98d7674..5f9c431 100644 --- a/cli/src/commands/returns/mod.rs +++ b/cli/src/commands/returns/mod.rs @@ -4,7 +4,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/returns/output.rs b/cli/src/commands/returns/output.rs index f4c904d..8e0745f 100644 --- a/cli/src/commands/returns/output.rs +++ b/cli/src/commands/returns/output.rs @@ -1,7 +1,7 @@ //! Output formatting for returns command results. use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::ReturnInfo; impl TableFormatter for ModuleGroupResult { diff --git a/cli/src/commands/reverse_trace/execute.rs b/cli/src/commands/reverse_trace/execute.rs index ecb9518..aa96d56 100644 --- a/cli/src/commands/reverse_trace/execute.rs +++ b/cli/src/commands/reverse_trace/execute.rs @@ -3,44 +3,85 @@ use std::error::Error; use super::ReverseTraceCmd; use crate::commands::Execute; -use crate::queries::reverse_trace::{reverse_trace_calls, ReverseTraceStep}; -use crate::types::{TraceDirection, TraceEntry, TraceResult}; - -impl TraceResult { - /// Build a flattened reverse-trace from ReverseTraceStep objects - pub fn from_steps( - target_module: String, - target_function: String, - max_depth: u32, - steps: Vec, - ) -> Self { - let mut entries = Vec::new(); - let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); - - if steps.is_empty() { - return Self::empty(target_module, target_function, max_depth, TraceDirection::Backward); - } +use db::queries::reverse_trace::{reverse_trace_calls, ReverseTraceStep}; +use db::types::{TraceDirection, TraceEntry, TraceResult}; + +/// Build a flattened reverse-trace from ReverseTraceStep objects +fn build_reverse_trace_result( + target_module: String, + target_function: String, + max_depth: u32, + steps: Vec, +) -> TraceResult { + let mut entries = Vec::new(); + let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); + + if steps.is_empty() { + return TraceResult::empty(target_module, target_function, max_depth, TraceDirection::Backward); + } - // Group steps by depth - let mut by_depth: HashMap> = HashMap::new(); - for step in &steps { - by_depth.entry(step.depth).or_default().push(step); + // Group steps by depth + let mut by_depth: HashMap> = HashMap::new(); + for step in &steps { + by_depth.entry(step.depth).or_default().push(step); + } + + // Process depth 1 (direct callers of target function) + if let Some(depth1_steps) = by_depth.get(&1) { + let mut filter = crate::dedup::DeduplicationFilter::new(); + + for step in depth1_steps { + let caller_key = ( + step.caller_module.clone(), + step.caller_function.clone(), + step.caller_arity, + 1i64, + ); + + // Add caller as root entry if not already added + if filter.should_process(caller_key.clone()) { + let entry_idx = entries.len(); + entries.push(TraceEntry { + module: step.caller_module.clone(), + function: step.caller_function.clone(), + arity: step.caller_arity, + kind: step.caller_kind.clone(), + start_line: step.caller_start_line, + end_line: step.caller_end_line, + file: step.file.clone(), + depth: 1, + line: step.line, + parent_index: None, + }); + entry_index_map.insert(caller_key, entry_idx); + } } + } - // Process depth 1 (direct callers of target function) - if let Some(depth1_steps) = by_depth.get(&1) { + // Process deeper levels (additional callers) + for depth in 2..=max_depth as i64 { + if let Some(depth_steps) = by_depth.get(&depth) { let mut filter = crate::dedup::DeduplicationFilter::new(); - for step in depth1_steps { + for step in depth_steps { let caller_key = ( step.caller_module.clone(), step.caller_function.clone(), step.caller_arity, - 1i64, + depth, + ); + + // Find parent index (the callee at previous depth, which is what called this caller) + let parent_key = ( + step.callee_module.clone(), + step.callee_function.clone(), + step.callee_arity, + depth - 1, ); - // Add caller as root entry if not already added - if filter.should_process(caller_key.clone()) { + let parent_index = entry_index_map.get(&parent_key).copied(); + + if filter.should_process(caller_key.clone()) && parent_index.is_some() { let entry_idx = entries.len(); entries.push(TraceEntry { module: step.caller_module.clone(), @@ -50,75 +91,32 @@ impl TraceResult { start_line: step.caller_start_line, end_line: step.caller_end_line, file: step.file.clone(), - depth: 1, + depth, line: step.line, - parent_index: None, + parent_index, }); entry_index_map.insert(caller_key, entry_idx); } } } + } - // Process deeper levels (additional callers) - for depth in 2..=max_depth as i64 { - if let Some(depth_steps) = by_depth.get(&depth) { - let mut filter = crate::dedup::DeduplicationFilter::new(); - - for step in depth_steps { - let caller_key = ( - step.caller_module.clone(), - step.caller_function.clone(), - step.caller_arity, - depth, - ); - - // Find parent index (the callee at previous depth, which is what called this caller) - let parent_key = ( - step.callee_module.clone(), - step.callee_function.clone(), - step.callee_arity, - depth - 1, - ); - - let parent_index = entry_index_map.get(&parent_key).copied(); - - if filter.should_process(caller_key.clone()) && parent_index.is_some() { - let entry_idx = entries.len(); - entries.push(TraceEntry { - module: step.caller_module.clone(), - function: step.caller_function.clone(), - arity: step.caller_arity, - kind: step.caller_kind.clone(), - start_line: step.caller_start_line, - end_line: step.caller_end_line, - file: step.file.clone(), - depth, - line: step.line, - parent_index, - }); - entry_index_map.insert(caller_key, entry_idx); - } - } - } - } - - let total_items = entries.len(); + let total_items = entries.len(); - Self { - module: target_module, - function: target_function, - max_depth, - direction: TraceDirection::Backward, - total_items, - entries, - } + TraceResult { + module: target_module, + function: target_function, + max_depth, + direction: TraceDirection::Backward, + total_items, + entries, } } impl Execute for ReverseTraceCmd { type Output = TraceResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let steps = reverse_trace_calls( db, &self.module, @@ -130,7 +128,7 @@ impl Execute for ReverseTraceCmd { self.common.limit, )?; - Ok(TraceResult::from_steps( + Ok(build_reverse_trace_result( self.module, self.function, self.depth, @@ -145,7 +143,7 @@ mod tests { #[test] fn test_empty_reverse_trace() { - let result = TraceResult::from_steps( + let result = build_reverse_trace_result( "TestModule".to_string(), "test_func".to_string(), 5, diff --git a/cli/src/commands/reverse_trace/mod.rs b/cli/src/commands/reverse_trace/mod.rs index 9b974b9..092523b 100644 --- a/cli/src/commands/reverse_trace/mod.rs +++ b/cli/src/commands/reverse_trace/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/reverse_trace/output_tests.rs b/cli/src/commands/reverse_trace/output_tests.rs index ab4cbe5..8aa0baa 100644 --- a/cli/src/commands/reverse_trace/output_tests.rs +++ b/cli/src/commands/reverse_trace/output_tests.rs @@ -2,7 +2,7 @@ #[cfg(test)] mod tests { - use crate::types::{TraceDirection, TraceEntry, TraceResult}; + use db::types::{TraceDirection, TraceEntry, TraceResult}; use rstest::{fixture, rstest}; // ========================================================================= diff --git a/cli/src/commands/search/execute.rs b/cli/src/commands/search/execute.rs index 410a224..065eeef 100644 --- a/cli/src/commands/search/execute.rs +++ b/cli/src/commands/search/execute.rs @@ -5,7 +5,7 @@ use serde::Serialize; use super::{SearchCmd, SearchKind}; use crate::commands::Execute; -use crate::queries::search::{search_functions, search_modules, FunctionResult as RawFunctionResult, ModuleResult}; +use db::queries::search::{search_functions, search_modules, FunctionResult as RawFunctionResult, ModuleResult}; /// A function found in search results #[derive(Debug, Clone, Serialize)] @@ -72,7 +72,7 @@ impl SearchResult { impl Execute for SearchCmd { type Output = SearchResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { match self.kind { SearchKind::Modules => { let modules = search_modules(db, &self.pattern, &self.common.project, self.common.limit, self.common.regex)?; diff --git a/cli/src/commands/search/mod.rs b/cli/src/commands/search/mod.rs index 3b4c2fa..828eb7e 100644 --- a/cli/src/commands/search/mod.rs +++ b/cli/src/commands/search/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::{Args, ValueEnum}; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/search/output_tests.rs b/cli/src/commands/search/output_tests.rs index 8a5785a..d895891 100644 --- a/cli/src/commands/search/output_tests.rs +++ b/cli/src/commands/search/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::{SearchFunc, SearchFuncModule, SearchResult}; - use crate::queries::search::ModuleResult; + use db::queries::search::ModuleResult; use rstest::{fixture, rstest}; // ========================================================================= @@ -115,7 +115,7 @@ MyApp.Accounts: test_name: test_format_json, fixture: modules_result, fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "modules.json"), + expected: db::test_utils::load_output_fixture("search", "modules.json"), format: Json, } @@ -123,7 +123,7 @@ MyApp.Accounts: test_name: test_format_toon, fixture: modules_result, fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "modules.toon"), + expected: db::test_utils::load_output_fixture("search", "modules.toon"), format: Toon, } @@ -131,7 +131,7 @@ MyApp.Accounts: test_name: test_format_toon_empty, fixture: empty_result, fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "empty.toon"), + expected: db::test_utils::load_output_fixture("search", "empty.toon"), format: Toon, } } diff --git a/cli/src/commands/setup/execute.rs b/cli/src/commands/setup/execute.rs index ee80a88..c87ab39 100644 --- a/cli/src/commands/setup/execute.rs +++ b/cli/src/commands/setup/execute.rs @@ -1,12 +1,12 @@ use std::error::Error; use std::fs; -use cozo::DbInstance; +use db::DbInstance; use include_dir::{include_dir, Dir}; use serde::Serialize; use super::SetupCmd; use crate::commands::Execute; -use crate::queries::schema; +use db::queries::schema; /// Embedded skill templates directory static SKILL_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/skills"); @@ -382,7 +382,7 @@ impl Execute for SetupCmd { #[cfg(test)] mod tests { use super::*; - use crate::db::open_db; + use db::open_db; use rstest::{fixture, rstest}; use tempfile::NamedTempFile; diff --git a/cli/src/commands/setup/mod.rs b/cli/src/commands/setup/mod.rs index 463dac9..2892646 100644 --- a/cli/src/commands/setup/mod.rs +++ b/cli/src/commands/setup/mod.rs @@ -3,7 +3,7 @@ mod output; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/struct_usage/execute.rs b/cli/src/commands/struct_usage/execute.rs index 6175720..4769265 100644 --- a/cli/src/commands/struct_usage/execute.rs +++ b/cli/src/commands/struct_usage/execute.rs @@ -5,8 +5,8 @@ use serde::Serialize; use super::StructUsageCmd; use crate::commands::Execute; -use crate::queries::struct_usage::{find_struct_usage, StructUsageEntry}; -use crate::types::ModuleGroupResult; +use db::queries::struct_usage::{find_struct_usage, StructUsageEntry}; +use db::types::ModuleGroupResult; /// A function that uses a struct type #[derive(Debug, Clone, Serialize)] @@ -44,117 +44,113 @@ pub enum StructUsageOutput { ByModule(StructModulesResult), } -impl ModuleGroupResult { - /// Build grouped result from flat StructUsageEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); - - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let usage_info = UsageInfo { - name: entry.name, - arity: entry.arity, - inputs: entry.inputs_string, - returns: entry.return_string, - line: entry.line, - }; - (entry.module, usage_info) - }); - - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } +/// Build grouped result from flat StructUsageEntry list +fn build_usage_info_result( + pattern: String, + module_filter: Option, + entries: Vec, +) -> ModuleGroupResult { + let total_items = entries.len(); + + // Use helper to group by module + let items = crate::utils::group_by_module(entries, |entry| { + let usage_info = UsageInfo { + name: entry.name, + arity: entry.arity, + inputs: entry.inputs_string, + returns: entry.return_string, + line: entry.line, + }; + (entry.module, usage_info) + }); + + ModuleGroupResult { + module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), + function_pattern: Some(pattern), + total_items, + items, } } -impl StructModulesResult { - /// Build aggregated result from flat StructUsageEntry list - fn from_entries(pattern: String, entries: Vec) -> Self { - // Aggregate by module, tracking which functions accept vs return - let mut module_map: BTreeMap> = BTreeMap::new(); - let mut module_accepts: BTreeMap> = BTreeMap::new(); - let mut module_returns: BTreeMap> = BTreeMap::new(); - - for entry in &entries { - // Track unique functions per module - module_map +/// Build aggregated result from flat StructUsageEntry list +fn build_struct_modules_result(pattern: String, entries: Vec) -> StructModulesResult { + // Aggregate by module, tracking which functions accept vs return + let mut module_map: BTreeMap> = BTreeMap::new(); + let mut module_accepts: BTreeMap> = BTreeMap::new(); + let mut module_returns: BTreeMap> = BTreeMap::new(); + + for entry in &entries { + // Track unique functions per module + module_map + .entry(entry.module.clone()) + .or_default() + .insert(format!("{}/{}", entry.name, entry.arity)); + + // Check if function accepts the type + if entry.inputs_string.contains(&pattern) { + module_accepts .entry(entry.module.clone()) .or_default() .insert(format!("{}/{}", entry.name, entry.arity)); + } - // Check if function accepts the type - if entry.inputs_string.contains(&pattern) { - module_accepts - .entry(entry.module.clone()) - .or_default() - .insert(format!("{}/{}", entry.name, entry.arity)); - } - - // Check if function returns the type - if entry.return_string.contains(&pattern) { - module_returns - .entry(entry.module.clone()) - .or_default() - .insert(format!("{}/{}", entry.name, entry.arity)); - } + // Check if function returns the type + if entry.return_string.contains(&pattern) { + module_returns + .entry(entry.module.clone()) + .or_default() + .insert(format!("{}/{}", entry.name, entry.arity)); } + } - // Convert to result type, sorted by total count descending - let mut modules: Vec = module_map - .into_iter() - .map(|(name, functions)| { - let accepts_count = module_accepts - .get(&name) - .map(|s| s.len() as i64) - .unwrap_or(0); - let returns_count = module_returns - .get(&name) - .map(|s| s.len() as i64) - .unwrap_or(0); - let total = functions.len() as i64; - - ModuleStructUsage { - name, - accepts_count, - returns_count, - total, - } - }) - .collect(); - - // Sort by total count descending, then by module name - modules.sort_by(|a, b| { - let cmp = b.total.cmp(&a.total); - if cmp == std::cmp::Ordering::Equal { - a.name.cmp(&b.name) - } else { - cmp + // Convert to result type, sorted by total count descending + let mut modules: Vec = module_map + .into_iter() + .map(|(name, functions)| { + let accepts_count = module_accepts + .get(&name) + .map(|s| s.len() as i64) + .unwrap_or(0); + let returns_count = module_returns + .get(&name) + .map(|s| s.len() as i64) + .unwrap_or(0); + let total = functions.len() as i64; + + ModuleStructUsage { + name, + accepts_count, + returns_count, + total, } - }); + }) + .collect(); + + // Sort by total count descending, then by module name + modules.sort_by(|a, b| { + let cmp = b.total.cmp(&a.total); + if cmp == std::cmp::Ordering::Equal { + a.name.cmp(&b.name) + } else { + cmp + } + }); - let total_modules = modules.len(); - let total_functions = entries.len(); + let total_modules = modules.len(); + let total_functions = entries.len(); - StructModulesResult { - struct_pattern: pattern, - total_modules, - total_functions, - modules, - } + StructModulesResult { + struct_pattern: pattern, + total_modules, + total_functions, + modules, } } impl Execute for StructUsageCmd { type Output = StructUsageOutput; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let entries = find_struct_usage( db, &self.pattern, @@ -166,11 +162,11 @@ impl Execute for StructUsageCmd { if self.by_module { Ok(StructUsageOutput::ByModule( - StructModulesResult::from_entries(self.pattern, entries), + build_struct_modules_result(self.pattern, entries), )) } else { Ok(StructUsageOutput::Detailed( - ModuleGroupResult::::from_entries(self.pattern, self.module, entries), + build_usage_info_result(self.pattern, self.module, entries), )) } } diff --git a/cli/src/commands/struct_usage/mod.rs b/cli/src/commands/struct_usage/mod.rs index a1c4f13..be61e19 100644 --- a/cli/src/commands/struct_usage/mod.rs +++ b/cli/src/commands/struct_usage/mod.rs @@ -11,7 +11,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/struct_usage/output.rs b/cli/src/commands/struct_usage/output.rs index a430ee2..6acb95f 100644 --- a/cli/src/commands/struct_usage/output.rs +++ b/cli/src/commands/struct_usage/output.rs @@ -4,7 +4,7 @@ use regex::Regex; use std::sync::LazyLock; use crate::output::{Outputable, TableFormatter}; -use crate::types::ModuleGroupResult; +use db::types::ModuleGroupResult; use super::execute::{UsageInfo, StructUsageOutput, StructModulesResult}; /// Regex to match Elixir struct maps like `%{__struct__: Module.Name, field: type(), ...}` diff --git a/cli/src/commands/struct_usage/output_tests.rs b/cli/src/commands/struct_usage/output_tests.rs index 715ae09..b1ed160 100644 --- a/cli/src/commands/struct_usage/output_tests.rs +++ b/cli/src/commands/struct_usage/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::{ModuleStructUsage, StructModulesResult, StructUsageOutput, UsageInfo}; - use crate::types::{ModuleGroup, ModuleGroupResult}; + use db::types::{ModuleGroup, ModuleGroupResult}; use rstest::{fixture, rstest}; // ========================================================================= diff --git a/cli/src/commands/trace/execute.rs b/cli/src/commands/trace/execute.rs index 7d560bb..d76fbba 100644 --- a/cli/src/commands/trace/execute.rs +++ b/cli/src/commands/trace/execute.rs @@ -3,69 +3,112 @@ use std::error::Error; use super::TraceCmd; use crate::commands::Execute; -use crate::queries::trace::trace_calls; -use crate::types::{Call, TraceDirection, TraceEntry, TraceResult}; - -impl TraceResult { - /// Build a flattened trace from Call objects - pub fn from_calls( - start_module: String, - start_function: String, - max_depth: u32, - calls: Vec, - ) -> Self { - let mut entries = Vec::new(); - let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); - - // Add the starting function as the root entry at depth 0 - entries.push(TraceEntry { - module: start_module.clone(), - function: start_function.clone(), - arity: 0, // Will be updated from first call if available - kind: String::new(), - start_line: 0, - end_line: 0, - file: String::new(), - depth: 0, - line: 0, - parent_index: None, - }); - entry_index_map.insert((start_module.clone(), start_function.clone(), 0, 0), 0); - - if calls.is_empty() { - return Self::empty(start_module, start_function, max_depth, TraceDirection::Forward); +use db::queries::trace::trace_calls; +use db::types::{Call, TraceDirection, TraceEntry, TraceResult}; + +fn build_trace_result( + start_module: String, + start_function: String, + max_depth: u32, + calls: Vec, +) -> TraceResult { + let mut entries = Vec::new(); + let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); + + // Add the starting function as the root entry at depth 0 + entries.push(TraceEntry { + module: start_module.clone(), + function: start_function.clone(), + arity: 0, // Will be updated from first call if available + kind: String::new(), + start_line: 0, + end_line: 0, + file: String::new(), + depth: 0, + line: 0, + parent_index: None, + }); + entry_index_map.insert((start_module.clone(), start_function.clone(), 0, 0), 0); + + if calls.is_empty() { + return TraceResult::empty(start_module, start_function, max_depth, TraceDirection::Forward); + } + + // Group calls by depth, consuming the Vec to take ownership + let mut by_depth: HashMap> = HashMap::new(); + for call in calls { + if let Some(depth) = call.depth { + by_depth.entry(depth).or_default().push(call); } + } - // Group calls by depth, consuming the Vec to take ownership - let mut by_depth: HashMap> = HashMap::new(); - for call in calls { - if let Some(depth) = call.depth { - by_depth.entry(depth).or_default().push(call); + // Process depth 1 (direct callees from start function) + if let Some(depth1_calls) = by_depth.remove(&1) { + // Track seen entries by index into entries vec (avoids storing strings) + let mut seen_at_depth: std::collections::HashSet = std::collections::HashSet::new(); + + for call in depth1_calls { + // Check if we already have this callee at this depth + let existing = entries.iter().position(|e| { + e.depth == 1 + && e.module == call.callee.module.as_ref() + && e.function == call.callee.name.as_ref() + && e.arity == call.callee.arity + }); + + if existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX)) { + if existing.is_none() { + let entry_idx = entries.len(); + // Convert from Rc to String for storage + let module = call.callee.module.to_string(); + let function = call.callee.name.to_string(); + let arity = call.callee.arity; + entry_index_map.insert((module.clone(), function.clone(), arity, 1i64), entry_idx); + entries.push(TraceEntry { + module, + function, + arity, + kind: call.callee.kind.as_deref().unwrap_or("").to_string(), + start_line: call.callee.start_line.unwrap_or(0), + end_line: call.callee.end_line.unwrap_or(0), + file: call.callee.file.as_deref().unwrap_or("").to_string(), + depth: 1, + line: call.line, + parent_index: Some(0), + }); + } } } + } - // Process depth 1 (direct callees from start function) - if let Some(depth1_calls) = by_depth.remove(&1) { - // Track seen entries by index into entries vec (avoids storing strings) - let mut seen_at_depth: std::collections::HashSet = std::collections::HashSet::new(); - - for call in depth1_calls { + // Process deeper levels + for depth in 2..=max_depth as i64 { + if let Some(depth_calls) = by_depth.remove(&depth) { + for call in depth_calls { // Check if we already have this callee at this depth let existing = entries.iter().position(|e| { - e.depth == 1 + e.depth == depth && e.module == call.callee.module.as_ref() && e.function == call.callee.name.as_ref() && e.arity == call.callee.arity }); - if existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX)) { - if existing.is_none() { + if existing.is_none() { + // Find parent index using references (no cloning) + let parent_index = entries.iter().position(|e| { + e.depth == depth - 1 + && e.module == call.caller.module.as_ref() + && e.function == call.caller.name.as_ref() + && e.arity == call.caller.arity + }); + + if parent_index.is_some() { let entry_idx = entries.len(); // Convert from Rc to String for storage let module = call.callee.module.to_string(); let function = call.callee.name.to_string(); let arity = call.callee.arity; - entry_index_map.insert((module.clone(), function.clone(), arity, 1i64), entry_idx); + entry_index_map.insert((module.clone(), function.clone(), arity, depth), entry_idx); entries.push(TraceEntry { module, function, @@ -74,78 +117,32 @@ impl TraceResult { start_line: call.callee.start_line.unwrap_or(0), end_line: call.callee.end_line.unwrap_or(0), file: call.callee.file.as_deref().unwrap_or("").to_string(), - depth: 1, + depth, line: call.line, - parent_index: Some(0), - }); - } - } - } - } - - // Process deeper levels - for depth in 2..=max_depth as i64 { - if let Some(depth_calls) = by_depth.remove(&depth) { - for call in depth_calls { - // Check if we already have this callee at this depth - let existing = entries.iter().position(|e| { - e.depth == depth - && e.module == call.callee.module.as_ref() - && e.function == call.callee.name.as_ref() - && e.arity == call.callee.arity - }); - - if existing.is_none() { - // Find parent index using references (no cloning) - let parent_index = entries.iter().position(|e| { - e.depth == depth - 1 - && e.module == call.caller.module.as_ref() - && e.function == call.caller.name.as_ref() - && e.arity == call.caller.arity + parent_index, }); - - if parent_index.is_some() { - let entry_idx = entries.len(); - // Convert from Rc to String for storage - let module = call.callee.module.to_string(); - let function = call.callee.name.to_string(); - let arity = call.callee.arity; - entry_index_map.insert((module.clone(), function.clone(), arity, depth), entry_idx); - entries.push(TraceEntry { - module, - function, - arity, - kind: call.callee.kind.as_deref().unwrap_or("").to_string(), - start_line: call.callee.start_line.unwrap_or(0), - end_line: call.callee.end_line.unwrap_or(0), - file: call.callee.file.as_deref().unwrap_or("").to_string(), - depth, - line: call.line, - parent_index, - }); - } } } } } + } - let total_items = entries.len() - 1; // Exclude the root entry from count + let total_items = entries.len() - 1; // Exclude the root entry from count - Self { - module: start_module, - function: start_function, - max_depth, - direction: TraceDirection::Forward, - total_items, - entries, - } + TraceResult { + module: start_module, + function: start_function, + max_depth, + direction: TraceDirection::Forward, + total_items, + entries, } } impl Execute for TraceCmd { type Output = TraceResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let calls = trace_calls( db, &self.module, @@ -157,7 +154,7 @@ impl Execute for TraceCmd { self.common.limit, )?; - Ok(TraceResult::from_calls( + Ok(build_trace_result( self.module, self.function, self.depth, @@ -172,7 +169,7 @@ mod tests { #[test] fn test_empty_trace() { - let result = TraceResult::from_calls("TestModule".to_string(), "test_func".to_string(), 5, vec![]); + let result = TraceResult::empty("TestModule".to_string(), "test_func".to_string(), 5, db::TraceDirection::Forward); assert_eq!(result.total_items, 0); assert_eq!(result.entries.len(), 0); } diff --git a/cli/src/commands/trace/mod.rs b/cli/src/commands/trace/mod.rs index 06faf02..6ecc5ab 100644 --- a/cli/src/commands/trace/mod.rs +++ b/cli/src/commands/trace/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/trace/output.rs b/cli/src/commands/trace/output.rs index a09379d..494307b 100644 --- a/cli/src/commands/trace/output.rs +++ b/cli/src/commands/trace/output.rs @@ -1,7 +1,7 @@ //! Output formatting for trace and reverse-trace command results. use crate::output::Outputable; -use crate::types::{TraceResult, TraceDirection}; +use db::types::{TraceResult, TraceDirection}; impl Outputable for TraceResult { fn to_table(&self) -> String { @@ -67,7 +67,7 @@ fn format_reverse_trace(result: &TraceResult) -> String { } /// Format a reverse trace entry (callers going up the chain) -fn format_reverse_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { +fn format_reverse_entry(lines: &mut Vec, entries: &[db::types::TraceEntry], idx: usize, depth: usize) { let entry = &entries[idx]; let indent = " ".repeat(depth); let kind_str = if entry.kind.is_empty() { @@ -104,7 +104,7 @@ fn format_reverse_entry(lines: &mut Vec, entries: &[crate::types::TraceE } /// Recursively format an entry and its children -fn format_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { +fn format_entry(lines: &mut Vec, entries: &[db::types::TraceEntry], idx: usize, depth: usize) { let entry = &entries[idx]; let indent = " ".repeat(depth); let kind_str = if entry.kind.is_empty() { @@ -133,7 +133,7 @@ fn format_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], i /// Format a child call/caller entry fn format_call( lines: &mut Vec, - entries: &[crate::types::TraceEntry], + entries: &[db::types::TraceEntry], idx: usize, depth: usize, parent_module: &str, diff --git a/cli/src/commands/trace/output_tests.rs b/cli/src/commands/trace/output_tests.rs index d26d11c..6b04d0e 100644 --- a/cli/src/commands/trace/output_tests.rs +++ b/cli/src/commands/trace/output_tests.rs @@ -2,7 +2,7 @@ #[cfg(test)] mod tests { - use crate::types::{TraceDirection, TraceEntry, TraceResult}; + use db::types::{TraceDirection, TraceEntry, TraceResult}; use rstest::{fixture, rstest}; // ========================================================================= diff --git a/cli/src/commands/unused/execute.rs b/cli/src/commands/unused/execute.rs index 77e86b2..632613a 100644 --- a/cli/src/commands/unused/execute.rs +++ b/cli/src/commands/unused/execute.rs @@ -4,8 +4,8 @@ use serde::Serialize; use super::UnusedCmd; use crate::commands::Execute; -use crate::queries::unused::{find_unused_functions, UnusedFunction}; -use crate::types::ModuleCollectionResult; +use db::queries::unused::{find_unused_functions, UnusedFunction}; +use db::types::ModuleCollectionResult; /// An unused function within a module #[derive(Debug, Clone, Serialize)] @@ -16,40 +16,38 @@ pub struct UnusedFunc { pub line: i64, } -impl ModuleCollectionResult { - /// Build grouped result from flat UnusedFunction list - fn from_functions( - module_pattern: String, - functions: Vec, - ) -> Self { - let total_items = functions.len(); +/// Build grouped result from flat UnusedFunction list +fn build_unused_functions_result( + module_pattern: String, + functions: Vec, +) -> ModuleCollectionResult { + let total_items = functions.len(); - // Use helper to group by module, tracking file for each module - let items = crate::utils::group_by_module_with_file(functions, |func| { - let unused_func = UnusedFunc { - name: func.name, - arity: func.arity, - kind: func.kind, - line: func.line, - }; - (func.module, unused_func, func.file) - }); + // Use helper to group by module, tracking file for each module + let items = crate::utils::group_by_module_with_file(functions, |func| { + let unused_func = UnusedFunc { + name: func.name, + arity: func.arity, + kind: func.kind, + line: func.line, + }; + (func.module, unused_func, func.file) + }); - ModuleCollectionResult { - module_pattern, - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items, - items, - } + ModuleCollectionResult { + module_pattern, + function_pattern: None, + kind_filter: None, + name_filter: None, + total_items, + items, } } impl Execute for UnusedCmd { type Output = ModuleCollectionResult; - fn execute(self, db: &cozo::DbInstance) -> Result> { + fn execute(self, db: &db::DbInstance) -> Result> { let functions = find_unused_functions( db, self.module.as_deref(), @@ -61,7 +59,7 @@ impl Execute for UnusedCmd { self.common.limit, )?; - Ok(>::from_functions( + Ok(build_unused_functions_result( self.module.unwrap_or_else(|| "*".to_string()), functions, )) diff --git a/cli/src/commands/unused/mod.rs b/cli/src/commands/unused/mod.rs index 2304e99..0c9f159 100644 --- a/cli/src/commands/unused/mod.rs +++ b/cli/src/commands/unused/mod.rs @@ -7,7 +7,7 @@ mod output_tests; use std::error::Error; use clap::Args; -use cozo::DbInstance; +use db::DbInstance; use crate::commands::{CommandRunner, CommonArgs, Execute}; use crate::output::{OutputFormat, Outputable}; diff --git a/cli/src/commands/unused/output.rs b/cli/src/commands/unused/output.rs index 2ca5e6b..5b4c78f 100644 --- a/cli/src/commands/unused/output.rs +++ b/cli/src/commands/unused/output.rs @@ -1,7 +1,7 @@ //! Output formatting for unused command results. use crate::output::Outputable; -use crate::types::ModuleCollectionResult; +use db::types::ModuleCollectionResult; use super::execute::UnusedFunc; impl Outputable for ModuleCollectionResult { diff --git a/cli/src/commands/unused/output_tests.rs b/cli/src/commands/unused/output_tests.rs index 096bb96..3e02a18 100644 --- a/cli/src/commands/unused/output_tests.rs +++ b/cli/src/commands/unused/output_tests.rs @@ -3,7 +3,7 @@ #[cfg(test)] mod tests { use super::super::execute::UnusedFunc; - use crate::types::{ModuleCollectionResult, ModuleGroup}; + use db::types::{ModuleCollectionResult, ModuleGroup}; use rstest::{fixture, rstest}; // ========================================================================= @@ -121,7 +121,7 @@ MyApp.Accounts (lib/accounts.ex): test_name: test_format_json, fixture: single_result, fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "single.json"), + expected: db::test_utils::load_output_fixture("unused", "single.json"), format: Json, } @@ -129,7 +129,7 @@ MyApp.Accounts (lib/accounts.ex): test_name: test_format_toon, fixture: single_result, fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "single.toon"), + expected: db::test_utils::load_output_fixture("unused", "single.toon"), format: Toon, } @@ -137,7 +137,7 @@ MyApp.Accounts (lib/accounts.ex): test_name: test_format_toon_empty, fixture: empty_result, fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "empty.toon"), + expected: db::test_utils::load_output_fixture("unused", "empty.toon"), format: Toon, } } diff --git a/cli/src/main.rs b/cli/src/main.rs index 63a857c..dd674cb 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -2,20 +2,14 @@ use clap::Parser; mod cli; mod commands; -mod db; mod dedup; pub mod output; -mod queries; -pub mod types; mod utils; #[macro_use] mod test_macros; -#[cfg(test)] -pub mod fixtures; -#[cfg(test)] -pub mod test_utils; use cli::Args; use commands::CommandRunner; +use db::open_db; fn main() -> Result<(), Box> { let args = Args::parse(); @@ -26,7 +20,7 @@ fn main() -> Result<(), Box> { std::fs::create_dir_all(".code_search").ok(); } - let db = db::open_db(&db_path)?; + let db = open_db(&db_path)?; let output = args.command.run(&db, args.format)?; println!("{}", output); Ok(()) diff --git a/cli/src/output.rs b/cli/src/output.rs index c52beb6..5f6b953 100644 --- a/cli/src/output.rs +++ b/cli/src/output.rs @@ -4,7 +4,7 @@ use clap::ValueEnum; use serde::Serialize; -use crate::types::{ModuleGroupResult, ModuleCollectionResult}; +use db::types::{ModuleGroupResult, ModuleCollectionResult}; /// Output format for command results #[derive(Debug, Clone, Copy, Default, ValueEnum)] @@ -118,7 +118,7 @@ pub trait TableFormatter { /// /// This is the shared implementation for both ModuleGroupResult and ModuleCollectionResult. /// Extracts the common logic to avoid duplication between the two impl blocks. -fn format_module_table(formatter: &F, items: &[crate::types::ModuleGroup], total_items: usize) -> String +fn format_module_table(formatter: &F, items: &[db::types::ModuleGroup], total_items: usize) -> String where F: TableFormatter, { diff --git a/cli/src/test_macros.rs b/cli/src/test_macros.rs index 021ee6d..ac81b03 100644 --- a/cli/src/test_macros.rs +++ b/cli/src/test_macros.rs @@ -219,8 +219,8 @@ macro_rules! execute_test_fixture { project: $project:literal $(,)? ) => { #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::setup_test_db($json, $project) + fn $name() -> db::DbInstance { + db::test_utils::setup_test_db($json, $project) } }; } @@ -245,8 +245,8 @@ macro_rules! shared_fixture { project: $project:literal $(,)? ) => { #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::call_graph_db($project) + fn $name() -> db::DbInstance { + db::test_utils::call_graph_db($project) } }; ( @@ -255,8 +255,8 @@ macro_rules! shared_fixture { project: $project:literal $(,)? ) => { #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::type_signatures_db($project) + fn $name() -> db::DbInstance { + db::test_utils::type_signatures_db($project) } }; ( @@ -265,8 +265,8 @@ macro_rules! shared_fixture { project: $project:literal $(,)? ) => { #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::structs_db($project) + fn $name() -> db::DbInstance { + db::test_utils::structs_db($project) } }; } @@ -280,7 +280,9 @@ macro_rules! execute_empty_db_test { ) => { #[rstest] fn test_empty_db() { - let result = crate::test_utils::execute_on_empty_db($cmd); + use crate::commands::Execute; + let db = db::test_utils::setup_empty_test_db(); + let result = $cmd.execute(&db); assert!(result.is_err()); } }; @@ -318,7 +320,7 @@ macro_rules! execute_test { assertions: |$result:ident| $assertions:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let $result = $cmd.execute(&$fixture).expect("Execute should succeed"); $assertions @@ -346,7 +348,7 @@ macro_rules! execute_no_match_test { empty_field: $field:ident $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert!(result.$field.is_empty(), concat!(stringify!($field), " should be empty")); @@ -376,7 +378,7 @@ macro_rules! execute_count_test { expected: $expected:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert_eq!(result.$field.len(), $expected, @@ -407,7 +409,7 @@ macro_rules! execute_field_test { expected: $expected:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert_eq!(result.$field, $expected, @@ -440,7 +442,7 @@ macro_rules! execute_first_item_test { expected: $expected:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert!(!result.$collection.is_empty(), concat!(stringify!($collection), " should not be empty")); @@ -472,7 +474,7 @@ macro_rules! execute_all_match_test { condition: |$item:ident| $cond:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert!(result.$collection.iter().all(|$item| $cond), @@ -503,7 +505,7 @@ macro_rules! execute_limit_test { limit: $limit:expr $(,)? ) => { #[rstest] - fn $test_name($fixture: cozo::DbInstance) { + fn $test_name($fixture: db::DbInstance) { use crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); assert!(result.$collection.len() <= $limit, diff --git a/cli/templates/agents/.gitkeep b/cli/templates/agents/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/cli/templates/hooks/.gitkeep b/cli/templates/hooks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/cli/templates/skills/.gitkeep b/cli/templates/skills/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/db/src/lib.rs b/db/src/lib.rs index ed2e691..491f1e4 100644 --- a/db/src/lib.rs +++ b/db/src/lib.rs @@ -13,6 +13,7 @@ pub mod fixtures; // Re-export commonly used items pub use db::{open_db, run_query, run_query_no_params, DbError, Params}; +pub use cozo::DbInstance; #[cfg(any(test, feature = "test-utils"))] pub use db::open_mem_db; diff --git a/db/src/types/trace.rs b/db/src/types/trace.rs index e971fc9..136cc06 100644 --- a/db/src/types/trace.rs +++ b/db/src/types/trace.rs @@ -1,6 +1,8 @@ //! Unified types for trace and reverse-trace commands. +use std::collections::HashMap; use serde::Serialize; +use crate::types::Call; /// Direction of trace traversal #[derive(Debug, Clone, Copy, Default, Serialize)] From abe315e9a05542825ce296e61f90163403301784 Mon Sep 17 00:00:00 2001 From: Simon Garcia Date: Tue, 23 Dec 2025 02:48:20 +0100 Subject: [PATCH 8/8] Fix tests and apply clippy improvements after workspace refactoring Fixed broken tests from workspace migration: - Update template paths in setup command to reference workspace root (Changed from $CARGO_MANIFEST_DIR/templates/ to $CARGO_MANIFEST_DIR/../templates/) - All 492 CLI tests + 40 DB tests now passing Enable previously ignored doctest: - Add proper imports to query_builders.rs doctest example - 1 doctest now passing (1 remains intentionally ignored) Apply clippy fixes (37 auto-fixes + 1 manual): - Use .as_deref() instead of .as_ref().map(|s| s.as_str()) - Use $crate instead of crate in test macro definitions - Fix PathBuf comparison in main.rs - Collapse nested if statements - Remove unused 'visited' parameter from dfs_find_cycles() (Algorithm already uses path vector for cycle detection) Clean up old src/ directory (231 files deleted): - Removed all files from previous single-crate structure - Workspace structure now complete with db/ and cli/ crates Results: - All 533 tests passing (492 CLI + 40 DB + 1 doctest) - Clippy warnings reduced from 41 to 15 (63% reduction) - Remaining warnings are acceptable design decisions --- CLAUDE.md | 74 +- cli/src/commands/accepts/output.rs | 2 +- cli/src/commands/browse_module/execute.rs | 10 +- cli/src/commands/browse_module/output.rs | 42 +- cli/src/commands/clusters/execute.rs | 2 +- cli/src/commands/cycles/execute.rs | 9 +- cli/src/commands/describe/output.rs | 18 +- cli/src/commands/function/output.rs | 2 +- cli/src/commands/returns/output.rs | 2 +- cli/src/commands/setup/execute.rs | 6 +- cli/src/commands/struct_usage/output.rs | 2 +- cli/src/commands/trace/execute.rs | 5 +- cli/src/main.rs | 2 +- cli/src/test_macros.rs | 80 +- cli/templates/agents/.gitkeep | 0 cli/templates/hooks/.gitkeep | 0 cli/templates/skills/.gitkeep | 0 db/src/db.rs | 10 +- db/src/queries/cycles.rs | 5 +- db/src/queries/hotspots.rs | 10 +- db/src/queries/import.rs | 4 +- db/src/queries/path.rs | 2 +- db/src/query_builders.rs | 4 +- db/src/types/trace.rs | 2 - src/cli.rs | 61 - src/commands/accepts/execute.rs | 69 - src/commands/accepts/mod.rs | 37 - src/commands/accepts/output.rs | 33 - src/commands/boundaries/execute.rs | 103 - src/commands/boundaries/mod.rs | 47 - src/commands/boundaries/output.rs | 79 - src/commands/browse_module/cli_tests.rs | 115 - src/commands/browse_module/execute.rs | 325 - src/commands/browse_module/execute_tests.rs | 323 - src/commands/browse_module/mod.rs | 79 - src/commands/browse_module/output.rs | 215 - src/commands/browse_module/output_tests.rs | 261 - src/commands/calls_from/cli_tests.rs | 74 - src/commands/calls_from/execute.rs | 101 - src/commands/calls_from/execute_tests.rs | 172 - src/commands/calls_from/mod.rs | 41 - src/commands/calls_from/output.rs | 48 - src/commands/calls_from/output_tests.rs | 162 - src/commands/calls_to/cli_tests.rs | 74 - src/commands/calls_to/execute.rs | 88 - src/commands/calls_to/execute_tests.rs | 202 - src/commands/calls_to/mod.rs | 42 - src/commands/calls_to/output.rs | 41 - src/commands/calls_to/output_tests.rs | 162 - src/commands/clusters/execute.rs | 390 - src/commands/clusters/mod.rs | 46 - src/commands/clusters/output.rs | 81 - src/commands/complexity/cli_tests.rs | 119 - src/commands/complexity/execute.rs | 85 - src/commands/complexity/execute_tests.rs | 169 - src/commands/complexity/mod.rs | 59 - src/commands/complexity/output.rs | 40 - src/commands/complexity/output_tests.rs | 123 - src/commands/cycles/execute.rs | 274 - src/commands/cycles/mod.rs | 45 - src/commands/cycles/output.rs | 125 - src/commands/depended_by/cli_tests.rs | 56 - src/commands/depended_by/execute.rs | 127 - src/commands/depended_by/execute_tests.rs | 112 - src/commands/depended_by/mod.rs | 34 - src/commands/depended_by/output.rs | 48 - src/commands/depended_by/output_tests.rs | 176 - src/commands/depends_on/cli_tests.rs | 56 - src/commands/depends_on/execute.rs | 83 - src/commands/depends_on/execute_tests.rs | 110 - src/commands/depends_on/mod.rs | 34 - src/commands/depends_on/output.rs | 37 - src/commands/depends_on/output_tests.rs | 194 - src/commands/describe/descriptions.rs | 488 - src/commands/describe/execute.rs | 146 - src/commands/describe/mod.rs | 30 - src/commands/describe/output.rs | 162 - src/commands/duplicates/cli_tests.rs | 107 - src/commands/duplicates/execute.rs | 191 - src/commands/duplicates/execute_tests.rs | 230 - src/commands/duplicates/mod.rs | 49 - src/commands/duplicates/output.rs | 90 - src/commands/duplicates/output_tests.rs | 541 - src/commands/function/cli_tests.rs | 88 - src/commands/function/execute.rs | 73 - src/commands/function/execute_tests.rs | 160 - src/commands/function/mod.rs | 43 - src/commands/function/output.rs | 41 - src/commands/function/output_tests.rs | 152 - src/commands/god_modules/execute.rs | 164 - src/commands/god_modules/mod.rs | 51 - src/commands/god_modules/output.rs | 55 - src/commands/hotspots/cli_tests.rs | 133 - src/commands/hotspots/execute.rs | 142 - src/commands/hotspots/execute_tests.rs | 170 - src/commands/hotspots/mod.rs | 56 - src/commands/hotspots/output.rs | 4 - src/commands/hotspots/output_tests.rs | 153 - src/commands/import/cli_tests.rs | 76 - src/commands/import/execute.rs | 247 - src/commands/import/mod.rs | 50 - src/commands/import/output.rs | 32 - src/commands/import/output_tests.rs | 119 - src/commands/large_functions/execute.rs | 108 - src/commands/large_functions/mod.rs | 46 - src/commands/large_functions/output.rs | 40 - src/commands/location/cli_tests.rs | 91 - src/commands/location/execute.rs | 131 - src/commands/location/execute_tests.rs | 320 - src/commands/location/mod.rs | 44 - src/commands/location/output.rs | 54 - src/commands/location/output_tests.rs | 169 - src/commands/many_clauses/execute.rs | 107 - src/commands/many_clauses/mod.rs | 47 - src/commands/many_clauses/output.rs | 40 - src/commands/mod.rs | 209 - src/commands/path/cli_tests.rs | 187 - src/commands/path/execute.rs | 48 - src/commands/path/execute_tests.rs | 209 - src/commands/path/mod.rs | 66 - src/commands/path/output.rs | 39 - src/commands/path/output_tests.rs | 122 - src/commands/returns/execute.rs | 67 - src/commands/returns/mod.rs | 37 - src/commands/returns/output.rs | 30 - src/commands/reverse_trace/cli_tests.rs | 115 - src/commands/reverse_trace/execute.rs | 157 - src/commands/reverse_trace/execute_tests.rs | 120 - src/commands/reverse_trace/mod.rs | 47 - src/commands/reverse_trace/output.rs | 4 - src/commands/reverse_trace/output_tests.rs | 138 - src/commands/search/cli_tests.rs | 92 - src/commands/search/execute.rs | 93 - src/commands/search/execute_tests.rs | 204 - src/commands/search/mod.rs | 50 - src/commands/search/output.rs | 48 - src/commands/search/output_tests.rs | 137 - src/commands/setup/execute.rs | 887 - src/commands/setup/mod.rs | 54 - src/commands/setup/output.rs | 189 - src/commands/struct_usage/cli_tests.rs | 91 - src/commands/struct_usage/execute.rs | 177 - src/commands/struct_usage/execute_tests.rs | 228 - src/commands/struct_usage/mod.rs | 49 - src/commands/struct_usage/output.rs | 140 - src/commands/struct_usage/output_tests.rs | 172 - src/commands/trace/cli_tests.rs | 117 - src/commands/trace/execute.rs | 179 - src/commands/trace/execute_tests.rs | 124 - src/commands/trace/mod.rs | 47 - src/commands/trace/output.rs | 179 - src/commands/trace/output_tests.rs | 165 - src/commands/unused/cli_tests.rs | 135 - src/commands/unused/execute.rs | 70 - src/commands/unused/execute_tests.rs | 195 - src/commands/unused/mod.rs | 50 - src/commands/unused/output.rs | 43 - src/commands/unused/output_tests.rs | 143 - src/db.rs | 504 - src/dedup.rs | 112 - src/fixtures/call_graph.json | 468 - src/fixtures/extracted_trace.json | 53152 ---------------- src/fixtures/mod.rs | 74 - src/fixtures/output/calls_from/empty.toon | 4 - src/fixtures/output/calls_from/single.json | 40 - src/fixtures/output/calls_from/single.toon | 27 - src/fixtures/output/calls_to/empty.toon | 4 - src/fixtures/output/calls_to/single.json | 36 - src/fixtures/output/calls_to/single.toon | 23 - src/fixtures/output/depended_by/empty.toon | 3 - src/fixtures/output/depended_by/single.json | 26 - src/fixtures/output/depended_by/single.toon | 13 - src/fixtures/output/depends_on/empty.toon | 3 - src/fixtures/output/depends_on/single.json | 34 - src/fixtures/output/depends_on/single.toon | 21 - src/fixtures/output/function/empty.toon | 4 - src/fixtures/output/function/single.json | 18 - src/fixtures/output/function/single.toon | 7 - src/fixtures/output/hotspots/empty.toon | 4 - src/fixtures/output/hotspots/single.json | 19 - src/fixtures/output/hotspots/single.toon | 7 - src/fixtures/output/import/full.json | 19 - src/fixtures/output/import/full.toon | 11 - src/fixtures/output/location/empty.toon | 4 - src/fixtures/output/location/single.json | 25 - src/fixtures/output/location/single.toon | 12 - src/fixtures/output/path/empty.toon | 6 - src/fixtures/output/path/single.json | 33 - src/fixtures/output/path/single.toon | 9 - src/fixtures/output/reverse_trace/empty.toon | 5 - src/fixtures/output/reverse_trace/single.json | 25 - src/fixtures/output/reverse_trace/single.toon | 14 - src/fixtures/output/search/empty.toon | 2 - src/fixtures/output/search/modules.json | 16 - src/fixtures/output/search/modules.toon | 5 - src/fixtures/output/trace/empty.toon | 5 - src/fixtures/output/trace/single.json | 25 - src/fixtures/output/trace/single.toon | 14 - src/fixtures/output/unused/empty.toon | 3 - src/fixtures/output/unused/single.json | 18 - src/fixtures/output/unused/single.toon | 7 - src/fixtures/structs.json | 33 - src/fixtures/type_signatures.json | 176 - src/main.rs | 33 - src/output.rs | 186 - src/queries/accepts.rs | 107 - src/queries/calls.rs | 131 - src/queries/calls_from.rs | 30 - src/queries/calls_to.rs | 30 - src/queries/clusters.rs | 58 - src/queries/complexity.rs | 112 - src/queries/cycles.rs | 93 - src/queries/depended_by.rs | 26 - src/queries/dependencies.rs | 113 - src/queries/depends_on.rs | 26 - src/queries/duplicates.rs | 106 - src/queries/file.rs | 99 - src/queries/function.rs | 92 - src/queries/hotspots.rs | 292 - src/queries/import.rs | 724 - src/queries/import_models.rs | 145 - src/queries/large_functions.rs | 103 - src/queries/location.rs | 121 - src/queries/many_clauses.rs | 105 - src/queries/mod.rs | 81 - src/queries/path.rs | 244 - src/queries/returns.rs | 104 - src/queries/reverse_trace.rs | 139 - src/queries/schema.rs | 180 - src/queries/search.rs | 117 - src/queries/specs.rs | 127 - src/queries/struct_usage.rs | 107 - src/queries/structs.rs | 124 - src/queries/trace.rs | 132 - src/queries/types.rs | 121 - src/queries/unused.rs | 135 - src/test_macros.rs | 658 - src/test_utils.rs | 90 - src/types/call.rs | 332 - src/types/mod.rs | 16 - src/types/results.rs | 38 - src/types/trace.rs | 53 - src/utils.rs | 684 - 243 files changed, 176 insertions(+), 77871 deletions(-) delete mode 100644 cli/templates/agents/.gitkeep delete mode 100644 cli/templates/hooks/.gitkeep delete mode 100644 cli/templates/skills/.gitkeep delete mode 100644 src/cli.rs delete mode 100644 src/commands/accepts/execute.rs delete mode 100644 src/commands/accepts/mod.rs delete mode 100644 src/commands/accepts/output.rs delete mode 100644 src/commands/boundaries/execute.rs delete mode 100644 src/commands/boundaries/mod.rs delete mode 100644 src/commands/boundaries/output.rs delete mode 100644 src/commands/browse_module/cli_tests.rs delete mode 100644 src/commands/browse_module/execute.rs delete mode 100644 src/commands/browse_module/execute_tests.rs delete mode 100644 src/commands/browse_module/mod.rs delete mode 100644 src/commands/browse_module/output.rs delete mode 100644 src/commands/browse_module/output_tests.rs delete mode 100644 src/commands/calls_from/cli_tests.rs delete mode 100644 src/commands/calls_from/execute.rs delete mode 100644 src/commands/calls_from/execute_tests.rs delete mode 100644 src/commands/calls_from/mod.rs delete mode 100644 src/commands/calls_from/output.rs delete mode 100644 src/commands/calls_from/output_tests.rs delete mode 100644 src/commands/calls_to/cli_tests.rs delete mode 100644 src/commands/calls_to/execute.rs delete mode 100644 src/commands/calls_to/execute_tests.rs delete mode 100644 src/commands/calls_to/mod.rs delete mode 100644 src/commands/calls_to/output.rs delete mode 100644 src/commands/calls_to/output_tests.rs delete mode 100644 src/commands/clusters/execute.rs delete mode 100644 src/commands/clusters/mod.rs delete mode 100644 src/commands/clusters/output.rs delete mode 100644 src/commands/complexity/cli_tests.rs delete mode 100644 src/commands/complexity/execute.rs delete mode 100644 src/commands/complexity/execute_tests.rs delete mode 100644 src/commands/complexity/mod.rs delete mode 100644 src/commands/complexity/output.rs delete mode 100644 src/commands/complexity/output_tests.rs delete mode 100644 src/commands/cycles/execute.rs delete mode 100644 src/commands/cycles/mod.rs delete mode 100644 src/commands/cycles/output.rs delete mode 100644 src/commands/depended_by/cli_tests.rs delete mode 100644 src/commands/depended_by/execute.rs delete mode 100644 src/commands/depended_by/execute_tests.rs delete mode 100644 src/commands/depended_by/mod.rs delete mode 100644 src/commands/depended_by/output.rs delete mode 100644 src/commands/depended_by/output_tests.rs delete mode 100644 src/commands/depends_on/cli_tests.rs delete mode 100644 src/commands/depends_on/execute.rs delete mode 100644 src/commands/depends_on/execute_tests.rs delete mode 100644 src/commands/depends_on/mod.rs delete mode 100644 src/commands/depends_on/output.rs delete mode 100644 src/commands/depends_on/output_tests.rs delete mode 100644 src/commands/describe/descriptions.rs delete mode 100644 src/commands/describe/execute.rs delete mode 100644 src/commands/describe/mod.rs delete mode 100644 src/commands/describe/output.rs delete mode 100644 src/commands/duplicates/cli_tests.rs delete mode 100644 src/commands/duplicates/execute.rs delete mode 100644 src/commands/duplicates/execute_tests.rs delete mode 100644 src/commands/duplicates/mod.rs delete mode 100644 src/commands/duplicates/output.rs delete mode 100644 src/commands/duplicates/output_tests.rs delete mode 100644 src/commands/function/cli_tests.rs delete mode 100644 src/commands/function/execute.rs delete mode 100644 src/commands/function/execute_tests.rs delete mode 100644 src/commands/function/mod.rs delete mode 100644 src/commands/function/output.rs delete mode 100644 src/commands/function/output_tests.rs delete mode 100644 src/commands/god_modules/execute.rs delete mode 100644 src/commands/god_modules/mod.rs delete mode 100644 src/commands/god_modules/output.rs delete mode 100644 src/commands/hotspots/cli_tests.rs delete mode 100644 src/commands/hotspots/execute.rs delete mode 100644 src/commands/hotspots/execute_tests.rs delete mode 100644 src/commands/hotspots/mod.rs delete mode 100644 src/commands/hotspots/output.rs delete mode 100644 src/commands/hotspots/output_tests.rs delete mode 100644 src/commands/import/cli_tests.rs delete mode 100644 src/commands/import/execute.rs delete mode 100644 src/commands/import/mod.rs delete mode 100644 src/commands/import/output.rs delete mode 100644 src/commands/import/output_tests.rs delete mode 100644 src/commands/large_functions/execute.rs delete mode 100644 src/commands/large_functions/mod.rs delete mode 100644 src/commands/large_functions/output.rs delete mode 100644 src/commands/location/cli_tests.rs delete mode 100644 src/commands/location/execute.rs delete mode 100644 src/commands/location/execute_tests.rs delete mode 100644 src/commands/location/mod.rs delete mode 100644 src/commands/location/output.rs delete mode 100644 src/commands/location/output_tests.rs delete mode 100644 src/commands/many_clauses/execute.rs delete mode 100644 src/commands/many_clauses/mod.rs delete mode 100644 src/commands/many_clauses/output.rs delete mode 100644 src/commands/mod.rs delete mode 100644 src/commands/path/cli_tests.rs delete mode 100644 src/commands/path/execute.rs delete mode 100644 src/commands/path/execute_tests.rs delete mode 100644 src/commands/path/mod.rs delete mode 100644 src/commands/path/output.rs delete mode 100644 src/commands/path/output_tests.rs delete mode 100644 src/commands/returns/execute.rs delete mode 100644 src/commands/returns/mod.rs delete mode 100644 src/commands/returns/output.rs delete mode 100644 src/commands/reverse_trace/cli_tests.rs delete mode 100644 src/commands/reverse_trace/execute.rs delete mode 100644 src/commands/reverse_trace/execute_tests.rs delete mode 100644 src/commands/reverse_trace/mod.rs delete mode 100644 src/commands/reverse_trace/output.rs delete mode 100644 src/commands/reverse_trace/output_tests.rs delete mode 100644 src/commands/search/cli_tests.rs delete mode 100644 src/commands/search/execute.rs delete mode 100644 src/commands/search/execute_tests.rs delete mode 100644 src/commands/search/mod.rs delete mode 100644 src/commands/search/output.rs delete mode 100644 src/commands/search/output_tests.rs delete mode 100644 src/commands/setup/execute.rs delete mode 100644 src/commands/setup/mod.rs delete mode 100644 src/commands/setup/output.rs delete mode 100644 src/commands/struct_usage/cli_tests.rs delete mode 100644 src/commands/struct_usage/execute.rs delete mode 100644 src/commands/struct_usage/execute_tests.rs delete mode 100644 src/commands/struct_usage/mod.rs delete mode 100644 src/commands/struct_usage/output.rs delete mode 100644 src/commands/struct_usage/output_tests.rs delete mode 100644 src/commands/trace/cli_tests.rs delete mode 100644 src/commands/trace/execute.rs delete mode 100644 src/commands/trace/execute_tests.rs delete mode 100644 src/commands/trace/mod.rs delete mode 100644 src/commands/trace/output.rs delete mode 100644 src/commands/trace/output_tests.rs delete mode 100644 src/commands/unused/cli_tests.rs delete mode 100644 src/commands/unused/execute.rs delete mode 100644 src/commands/unused/execute_tests.rs delete mode 100644 src/commands/unused/mod.rs delete mode 100644 src/commands/unused/output.rs delete mode 100644 src/commands/unused/output_tests.rs delete mode 100644 src/db.rs delete mode 100644 src/dedup.rs delete mode 100644 src/fixtures/call_graph.json delete mode 100644 src/fixtures/extracted_trace.json delete mode 100644 src/fixtures/mod.rs delete mode 100644 src/fixtures/output/calls_from/empty.toon delete mode 100644 src/fixtures/output/calls_from/single.json delete mode 100644 src/fixtures/output/calls_from/single.toon delete mode 100644 src/fixtures/output/calls_to/empty.toon delete mode 100644 src/fixtures/output/calls_to/single.json delete mode 100644 src/fixtures/output/calls_to/single.toon delete mode 100644 src/fixtures/output/depended_by/empty.toon delete mode 100644 src/fixtures/output/depended_by/single.json delete mode 100644 src/fixtures/output/depended_by/single.toon delete mode 100644 src/fixtures/output/depends_on/empty.toon delete mode 100644 src/fixtures/output/depends_on/single.json delete mode 100644 src/fixtures/output/depends_on/single.toon delete mode 100644 src/fixtures/output/function/empty.toon delete mode 100644 src/fixtures/output/function/single.json delete mode 100644 src/fixtures/output/function/single.toon delete mode 100644 src/fixtures/output/hotspots/empty.toon delete mode 100644 src/fixtures/output/hotspots/single.json delete mode 100644 src/fixtures/output/hotspots/single.toon delete mode 100644 src/fixtures/output/import/full.json delete mode 100644 src/fixtures/output/import/full.toon delete mode 100644 src/fixtures/output/location/empty.toon delete mode 100644 src/fixtures/output/location/single.json delete mode 100644 src/fixtures/output/location/single.toon delete mode 100644 src/fixtures/output/path/empty.toon delete mode 100644 src/fixtures/output/path/single.json delete mode 100644 src/fixtures/output/path/single.toon delete mode 100644 src/fixtures/output/reverse_trace/empty.toon delete mode 100644 src/fixtures/output/reverse_trace/single.json delete mode 100644 src/fixtures/output/reverse_trace/single.toon delete mode 100644 src/fixtures/output/search/empty.toon delete mode 100644 src/fixtures/output/search/modules.json delete mode 100644 src/fixtures/output/search/modules.toon delete mode 100644 src/fixtures/output/trace/empty.toon delete mode 100644 src/fixtures/output/trace/single.json delete mode 100644 src/fixtures/output/trace/single.toon delete mode 100644 src/fixtures/output/unused/empty.toon delete mode 100644 src/fixtures/output/unused/single.json delete mode 100644 src/fixtures/output/unused/single.toon delete mode 100644 src/fixtures/structs.json delete mode 100644 src/fixtures/type_signatures.json delete mode 100644 src/main.rs delete mode 100644 src/output.rs delete mode 100644 src/queries/accepts.rs delete mode 100644 src/queries/calls.rs delete mode 100644 src/queries/calls_from.rs delete mode 100644 src/queries/calls_to.rs delete mode 100644 src/queries/clusters.rs delete mode 100644 src/queries/complexity.rs delete mode 100644 src/queries/cycles.rs delete mode 100644 src/queries/depended_by.rs delete mode 100644 src/queries/dependencies.rs delete mode 100644 src/queries/depends_on.rs delete mode 100644 src/queries/duplicates.rs delete mode 100644 src/queries/file.rs delete mode 100644 src/queries/function.rs delete mode 100644 src/queries/hotspots.rs delete mode 100644 src/queries/import.rs delete mode 100644 src/queries/import_models.rs delete mode 100644 src/queries/large_functions.rs delete mode 100644 src/queries/location.rs delete mode 100644 src/queries/many_clauses.rs delete mode 100644 src/queries/mod.rs delete mode 100644 src/queries/path.rs delete mode 100644 src/queries/returns.rs delete mode 100644 src/queries/reverse_trace.rs delete mode 100644 src/queries/schema.rs delete mode 100644 src/queries/search.rs delete mode 100644 src/queries/specs.rs delete mode 100644 src/queries/struct_usage.rs delete mode 100644 src/queries/structs.rs delete mode 100644 src/queries/trace.rs delete mode 100644 src/queries/types.rs delete mode 100644 src/queries/unused.rs delete mode 100644 src/test_macros.rs delete mode 100644 src/test_utils.rs delete mode 100644 src/types/call.rs delete mode 100644 src/types/mod.rs delete mode 100644 src/types/results.rs delete mode 100644 src/types/trace.rs delete mode 100644 src/utils.rs diff --git a/CLAUDE.md b/CLAUDE.md index 28240f9..1fdd3a9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,30 +5,64 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Build & Test Commands ```bash -cargo build # Build the project -cargo test # Run all tests +cargo build # Build entire workspace +cargo build -p cli # Build CLI binary only +cargo build -p db # Build database library only +cargo test # Run all tests in workspace +cargo test -p db # Test database layer only +cargo test -p code_search # Test CLI layer only cargo test # Run a single test by name cargo nextest run # Alternative test runner (faster) -cargo run -- --help # Show CLI help -cargo run -- describe # Show detailed command documentation +cargo run -p code_search -- --help # Show CLI help +cargo run -p code_search -- describe # Show detailed command documentation ``` +## Workspace Structure + +This is a Cargo workspace with two crates: + +- **`db/`** - Database library crate + - CozoDB query layer (all `queries/` modules) + - Database utilities (`db.rs`) + - Shared types (`types/`) + - Query builders (`query_builders.rs`) + - Test utilities and fixtures (behind `test-utils` feature flag) + +- **`cli/`** - CLI binary crate (package name: `code_search`) + - Command-line interface (`cli.rs`, `main.rs`) + - All command modules (`commands/`) + - Output formatting (`output.rs`) + - Presentation utilities (`utils.rs`, `dedup.rs`) + - Test macros (`test_macros.rs`) + +**Dependency flow:** `cli` depends on `db` via `db = { path = "../db" }`. The database layer is completely independent of the CLI. + +**Test utilities:** Database test helpers and fixtures are available via the `test-utils` feature. CLI tests use: `db = { path = "../db", features = ["test-utils"] }` + ## Architecture This is a Rust CLI tool for querying call graph data stored in a CozoDB SQLite database. Uses Rust 2024 edition with clap derive macros for CLI parsing. **Code organization:** -- `src/main.rs` - Entry point, module declarations -- `src/cli.rs` - Top-level CLI structure with global `--db` and `--format` flags -- `src/commands/mod.rs` - `Command` enum, `Execute` trait, `CommonArgs`, dispatch via enum_dispatch -- `src/commands//` - Individual command modules (directory structure) -- `src/queries/.rs` - CozoScript queries and result parsing (separate from command logic) -- `src/db.rs` - Database connection and query utilities -- `src/output.rs` - `OutputFormat` enum, `Outputable` and `TableFormatter` traits -- `src/dedup.rs` - Deduplication utilities (`sort_and_deduplicate`, `DeduplicationFilter`) -- `src/utils.rs` - Module grouping helpers (`group_by_module`, `convert_to_module_groups`) -- `src/types/` - Shared types (`ModuleGroupResult`, `ModuleGroup`, `Call`, etc.) -- `src/test_macros.rs` - Declarative test macros for CLI, execute, and output tests + +*Database crate (`db/src/`):* +- `lib.rs` - Public API surface, re-exports +- `db.rs` - Database connection and query utilities +- `queries/.rs` - CozoScript queries and result parsing (31 query modules) +- `query_builders.rs` - SQL condition builders (`ConditionBuilder`, `OptionalConditionBuilder`) +- `types/` - Shared types (`ModuleGroupResult`, `ModuleGroup`, `Call`, `FunctionRef`, etc.) +- `fixtures/` - Test data (feature-gated) +- `test_utils.rs` - Test helpers (feature-gated) + +*CLI crate (`cli/src/`):* +- `main.rs` - Entry point, module declarations +- `cli.rs` - Top-level CLI structure with global `--db` and `--format` flags +- `commands/mod.rs` - `Command` enum, `Execute` trait, `CommonArgs`, dispatch via enum_dispatch +- `commands//` - Individual command modules (27 commands, directory structure) +- `output.rs` - `OutputFormat` enum, `Outputable` and `TableFormatter` traits +- `dedup.rs` - Deduplication utilities (`sort_and_deduplicate`, `DeduplicationFilter`) +- `utils.rs` - Presentation helpers (`group_by_module`, `convert_to_module_groups`, `format_type_definition`) +- `test_macros.rs` - Declarative test macros for CLI, execute, and output tests **Command module structure:** Each command is a directory module with these files: @@ -39,9 +73,10 @@ Each command is a directory module with these files: **Execute trait:** ```rust +// Defined in cli/src/commands/mod.rs pub trait Execute { type Output: Outputable; - fn execute(self, db: &DbInstance) -> Result>; + fn execute(self, db: &db::DbInstance) -> Result>; } ``` @@ -67,7 +102,7 @@ pub trait Execute { When refactoring output, ensure all three formats remain consistent: 1. The struct hierarchy should make sense for both JSON and toon -2. Test fixtures exist in `src/fixtures/output//` for JSON and toon +2. Test fixtures exist in `db/src/fixtures/output//` for JSON and toon 3. Output tests verify round-trip consistency between formats **Dispatch flow:** @@ -96,8 +131,9 @@ pub struct MyCmd { - Uses `tempfile` for filesystem-based tests - Tests live alongside implementation in each module - Output tests use expected string constants for clarity -- Test macros in `src/test_macros.rs` reduce boilerplate (see `docs/TESTING_STRATEGY.md`) -- Shared fixtures in `src/fixtures/` for database and output tests +- Test macros in `cli/src/test_macros.rs` reduce boilerplate (see `docs/TESTING_STRATEGY.md`) +- Shared fixtures in `db/src/fixtures/` for database and output tests +- Database test utilities available via `db` crate with `test-utils` feature - Run with `cargo test` or `cargo nextest run` **Adding new commands:** diff --git a/cli/src/commands/accepts/output.rs b/cli/src/commands/accepts/output.rs index d01382a..5b0b984 100644 --- a/cli/src/commands/accepts/output.rs +++ b/cli/src/commands/accepts/output.rs @@ -8,7 +8,7 @@ impl TableFormatter for ModuleGroupResult { type Entry = AcceptsInfo; fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + let pattern = self.function_pattern.as_deref().unwrap_or("*"); format!("Functions accepting \"{}\"", pattern) } diff --git a/cli/src/commands/browse_module/execute.rs b/cli/src/commands/browse_module/execute.rs index 0bf4379..7714ceb 100644 --- a/cli/src/commands/browse_module/execute.rs +++ b/cli/src/commands/browse_module/execute.rs @@ -140,11 +140,10 @@ impl Execute for BrowseModuleCmd { for func in funcs { // Filter by name if specified - if let Some(ref name_filter) = self.name { - if !func.name.contains(name_filter) { + if let Some(ref name_filter) = self.name + && !func.name.contains(name_filter) { continue; } - } definitions.push(Definition::Function { module: func.module, @@ -220,11 +219,10 @@ impl Execute for BrowseModuleCmd { for struct_def in structs { // Filter by name if specified - if let Some(ref name_filter) = self.name { - if !struct_def.module.contains(name_filter) { + if let Some(ref name_filter) = self.name + && !struct_def.module.contains(name_filter) { continue; } - } definitions.push(Definition::Struct { module: struct_def.module.clone(), diff --git a/cli/src/commands/browse_module/output.rs b/cli/src/commands/browse_module/output.rs index 869a53b..e6f0062 100644 --- a/cli/src/commands/browse_module/output.rs +++ b/cli/src/commands/browse_module/output.rs @@ -28,17 +28,14 @@ impl Outputable for BrowseModuleResult { } // Summary - output.push_str(&format!( - "Found {} definition(s):\n\n", - self.total_items - )); + output.push_str(&format!("Found {} definition(s):\n\n", self.total_items)); // Group by module for readability let mut by_module: BTreeMap> = BTreeMap::new(); for def in &self.definitions { by_module .entry(def.module().to_string()) - .or_insert_with(Vec::new) + .or_default() .push(def); } @@ -58,9 +55,14 @@ impl Outputable for BrowseModuleResult { return_type, .. } => { - output.push_str(&format!(" L{}-{} [{}] {}/{}\n", start_line, end_line, kind, name, arity)); + output.push_str(&format!( + " L{}-{} [{}] {}/{}\n", + start_line, end_line, kind, name, arity + )); if !args.is_empty() || !return_type.is_empty() { - output.push_str(&format!(" {} {}\n", args, return_type).trim_end()); + output.push_str( + format!(" {} {}\n", args, return_type).trim_end(), + ); output.push('\n'); } } @@ -73,7 +75,10 @@ impl Outputable for BrowseModuleResult { full, .. } => { - output.push_str(&format!(" L{:<3} [{}] {}/{}\n", line, kind, name, arity)); + output.push_str(&format!( + " L{:<3} [{}] {}/{}\n", + line, kind, name, arity + )); if !full.is_empty() { output.push_str(&format!(" {}\n", full)); } @@ -89,25 +94,28 @@ impl Outputable for BrowseModuleResult { output.push_str(&format!(" L{:<3} [{}] {}\n", line, kind, name)); if !definition.is_empty() { let formatted = format_type_definition(definition); - // Indent multi-line definitions properly - for (i, def_line) in formatted.lines().enumerate() { - if i == 0 { - output.push_str(&format!(" {}\n", def_line)); - } else { - output.push_str(&format!(" {}\n", def_line)); - } + for def_line in formatted.lines() { + output.push_str(&format!(" {}\n", def_line)); } } } Definition::Struct { name, fields, .. } => { - output.push_str(&format!(" [struct] {} with {} fields\n", name, fields.len())); + output.push_str(&format!( + " [struct] {} with {} fields\n", + name, + fields.len() + )); for field in fields.iter() { output.push_str(&format!( " - {}: {} {}\n", field.name, field.inferred_type, - if field.required { "(required)" } else { "(optional)" } + if field.required { + "(required)" + } else { + "(optional)" + } )); } } diff --git a/cli/src/commands/clusters/execute.rs b/cli/src/commands/clusters/execute.rs index cfe3f0a..2bf3ec7 100644 --- a/cli/src/commands/clusters/execute.rs +++ b/cli/src/commands/clusters/execute.rs @@ -72,7 +72,7 @@ impl Execute for ClustersCmd { let namespace = extract_namespace(module, self.depth); namespace_modules .entry(namespace) - .or_insert_with(HashSet::new) + .or_default() .insert(module.clone()); } diff --git a/cli/src/commands/cycles/execute.rs b/cli/src/commands/cycles/execute.rs index b0d5a15..cda8cda 100644 --- a/cli/src/commands/cycles/execute.rs +++ b/cli/src/commands/cycles/execute.rs @@ -55,7 +55,7 @@ impl Execute for CyclesCmd { for edge in &edges { graph .entry(edge.from.clone()) - .or_insert_with(Vec::new) + .or_default() .push(edge.to.clone()); all_modules.insert(edge.from.clone()); all_modules.insert(edge.to.clone()); @@ -96,7 +96,7 @@ fn find_all_cycles(graph: &HashMap>, all_modules: &HashSet, - visited: &mut HashSet, ) -> Vec { let mut cycles = Vec::new(); let mut new_path = path.clone(); @@ -120,7 +119,7 @@ fn dfs_find_cycles( if current == start && !path.is_empty() { // Only report if we haven't already found this cycle // (cycles of length > 1 where start != first path node) - if path.len() > 0 { + if !path.is_empty() { cycles.push(Cycle { length: new_path.len() - 1, // Don't count the repeated start node modules: path.clone(), @@ -137,7 +136,7 @@ fn dfs_find_cycles( // Explore neighbors if let Some(neighbors) = graph.get(current) { for neighbor in neighbors { - let found = dfs_find_cycles(graph, neighbor, start, new_path.clone(), visited); + let found = dfs_find_cycles(graph, neighbor, start, new_path.clone()); cycles.extend(found); } } diff --git a/cli/src/commands/describe/output.rs b/cli/src/commands/describe/output.rs index 7353376..07b13af 100644 --- a/cli/src/commands/describe/output.rs +++ b/cli/src/commands/describe/output.rs @@ -16,14 +16,14 @@ impl Outputable for DescribeResult { fn format_list_all(categories: &[CategoryListing]) -> String { let mut output = String::new(); output.push_str("Available Commands\n"); - output.push_str("\n"); + output.push('\n'); for category in categories { output.push_str(&format!("{}:\n", category.category)); for (name, brief) in &category.commands { output.push_str(&format!(" {:<20} {}\n", name, brief)); } - output.push_str("\n"); + output.push('\n'); } output.push_str("Use 'code_search describe ' for detailed information.\n"); @@ -35,24 +35,24 @@ fn format_specific(descriptions: &[CommandDescription]) -> String { for (i, desc) in descriptions.iter().enumerate() { if i > 0 { - output.push_str("\n"); + output.push('\n'); output.push_str("================================================================================\n"); - output.push_str("\n"); + output.push('\n'); } // Title output.push_str(&format!("{} - {}\n", desc.name, desc.brief)); - output.push_str("\n"); + output.push('\n'); // Description output.push_str("DESCRIPTION\n"); output.push_str(&format!(" {}\n", desc.description)); - output.push_str("\n"); + output.push('\n'); // Usage output.push_str("USAGE\n"); output.push_str(&format!(" {}\n", desc.usage)); - output.push_str("\n"); + output.push('\n'); // Examples if !desc.examples.is_empty() { @@ -60,7 +60,7 @@ fn format_specific(descriptions: &[CommandDescription]) -> String { for example in &desc.examples { output.push_str(&format!(" # {}\n", example.description)); output.push_str(&format!(" {}\n", example.command)); - output.push_str("\n"); + output.push('\n'); } } @@ -70,7 +70,7 @@ fn format_specific(descriptions: &[CommandDescription]) -> String { for related in &desc.related { output.push_str(&format!(" {}\n", related)); } - output.push_str("\n"); + output.push('\n'); } } diff --git a/cli/src/commands/function/output.rs b/cli/src/commands/function/output.rs index 76dbeab..8e6b987 100644 --- a/cli/src/commands/function/output.rs +++ b/cli/src/commands/function/output.rs @@ -8,7 +8,7 @@ impl TableFormatter for ModuleGroupResult { type Entry = FuncSig; fn format_header(&self) -> String { - let function_pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + let function_pattern = self.function_pattern.as_deref().unwrap_or("*"); format!("Function: {}.{}", self.module_pattern, function_pattern) } diff --git a/cli/src/commands/returns/output.rs b/cli/src/commands/returns/output.rs index 8e0745f..b206683 100644 --- a/cli/src/commands/returns/output.rs +++ b/cli/src/commands/returns/output.rs @@ -8,7 +8,7 @@ impl TableFormatter for ModuleGroupResult { type Entry = ReturnInfo; fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + let pattern = self.function_pattern.as_deref().unwrap_or("*"); format!("Functions returning \"{}\"", pattern) } diff --git a/cli/src/commands/setup/execute.rs b/cli/src/commands/setup/execute.rs index c87ab39..b98597e 100644 --- a/cli/src/commands/setup/execute.rs +++ b/cli/src/commands/setup/execute.rs @@ -9,13 +9,13 @@ use crate::commands::Execute; use db::queries::schema; /// Embedded skill templates directory -static SKILL_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/skills"); +static SKILL_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/../templates/skills"); /// Embedded agent templates directory -static AGENT_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/agents"); +static AGENT_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/../templates/agents"); /// Embedded hook templates directory -static HOOK_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/hooks"); +static HOOK_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/../templates/hooks"); /// Status of a database relation (table) #[derive(Debug, Clone, Serialize)] diff --git a/cli/src/commands/struct_usage/output.rs b/cli/src/commands/struct_usage/output.rs index 6acb95f..c5fb9ab 100644 --- a/cli/src/commands/struct_usage/output.rs +++ b/cli/src/commands/struct_usage/output.rs @@ -22,7 +22,7 @@ impl TableFormatter for ModuleGroupResult { type Entry = UsageInfo; fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); + let pattern = self.function_pattern.as_deref().unwrap_or("*"); format!("Functions using \"{}\"", pattern) } diff --git a/cli/src/commands/trace/execute.rs b/cli/src/commands/trace/execute.rs index d76fbba..a4a28d3 100644 --- a/cli/src/commands/trace/execute.rs +++ b/cli/src/commands/trace/execute.rs @@ -56,8 +56,8 @@ fn build_trace_result( && e.arity == call.callee.arity }); - if existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX)) { - if existing.is_none() { + if (existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX))) + && existing.is_none() { let entry_idx = entries.len(); // Convert from Rc to String for storage let module = call.callee.module.to_string(); @@ -77,7 +77,6 @@ fn build_trace_result( parent_index: Some(0), }); } - } } } diff --git a/cli/src/main.rs b/cli/src/main.rs index dd674cb..06b8ba4 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -16,7 +16,7 @@ fn main() -> Result<(), Box> { let db_path = cli::resolve_db_path(args.db); // Create .code_search directory if using default path - if db_path == std::path::PathBuf::from(".code_search/cozo.sqlite") { + if db_path.as_path() == std::path::Path::new(".code_search/cozo.sqlite") { std::fs::create_dir_all(".code_search").ok(); } diff --git a/cli/src/test_macros.rs b/cli/src/test_macros.rs index ac81b03..3300d75 100644 --- a/cli/src/test_macros.rs +++ b/cli/src/test_macros.rs @@ -19,7 +19,7 @@ macro_rules! cli_defaults_test { fn test_defaults() { let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); match args.command { - crate::commands::Command::$variant(cmd) => { + $crate::commands::Command::$variant(cmd) => { $( assert_eq!(cmd.$($def_field).+, $def_expected, concat!("Default value mismatch for field: ", stringify!($($def_field).+))); @@ -50,7 +50,7 @@ macro_rules! cli_option_test { $($arg),+ ]).unwrap(); match args.command { - crate::commands::Command::$variant(cmd) => { + $crate::commands::Command::$variant(cmd) => { assert_eq!(cmd.$($field).+, $expected, concat!("Field ", stringify!($($field).+), " mismatch")); } @@ -81,7 +81,7 @@ macro_rules! cli_option_test_with_required { $($arg),+ ]).unwrap(); match args.command { - crate::commands::Command::$variant(cmd) => { + $crate::commands::Command::$variant(cmd) => { assert_eq!(cmd.$($field).+, $expected, concat!("Field ", stringify!($($field).+), " mismatch")); } @@ -108,7 +108,7 @@ macro_rules! cli_limit_tests { fn test_limit_default() { let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); match args.command { - crate::commands::Command::$variant(cmd) => { + $crate::commands::Command::$variant(cmd) => { assert_eq!(cmd.$($limit_field).+, $limit_default); } _ => panic!(concat!("Expected ", stringify!($variant), " command")), @@ -280,7 +280,7 @@ macro_rules! execute_empty_db_test { ) => { #[rstest] fn test_empty_db() { - use crate::commands::Execute; + use $crate::commands::Execute; let db = db::test_utils::setup_empty_test_db(); let result = $cmd.execute(&db); assert!(result.is_err()); @@ -321,7 +321,7 @@ macro_rules! execute_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let $result = $cmd.execute(&$fixture).expect("Execute should succeed"); $assertions } @@ -349,9 +349,12 @@ macro_rules! execute_no_match_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$field.is_empty(), concat!(stringify!($field), " should be empty")); + assert!( + result.$field.is_empty(), + concat!(stringify!($field), " should be empty") + ); } }; } @@ -379,10 +382,13 @@ macro_rules! execute_count_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert_eq!(result.$field.len(), $expected, - concat!("Expected ", stringify!($expected), " ", stringify!($field))); + assert_eq!( + result.$field.len(), + $expected, + concat!("Expected ", stringify!($expected), " ", stringify!($field)) + ); } }; } @@ -410,10 +416,12 @@ macro_rules! execute_field_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert_eq!(result.$field, $expected, - concat!("Field ", stringify!($field), " mismatch")); + assert_eq!( + result.$field, $expected, + concat!("Field ", stringify!($field), " mismatch") + ); } }; } @@ -443,11 +451,16 @@ macro_rules! execute_first_item_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(!result.$collection.is_empty(), concat!(stringify!($collection), " should not be empty")); - assert_eq!(result.$collection[0].$field, $expected, - concat!("First item ", stringify!($field), " mismatch")); + assert!( + !result.$collection.is_empty(), + concat!(stringify!($collection), " should not be empty") + ); + assert_eq!( + result.$collection[0].$field, $expected, + concat!("First item ", stringify!($field), " mismatch") + ); } }; } @@ -475,10 +488,12 @@ macro_rules! execute_all_match_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$collection.iter().all(|$item| $cond), - concat!("Not all ", stringify!($collection), " matched condition")); + assert!( + result.$collection.iter().all(|$item| $cond), + concat!("Not all ", stringify!($collection), " matched condition") + ); } }; } @@ -506,10 +521,17 @@ macro_rules! execute_limit_test { ) => { #[rstest] fn $test_name($fixture: db::DbInstance) { - use crate::commands::Execute; + use $crate::commands::Execute; let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$collection.len() <= $limit, - concat!("Expected at most ", stringify!($limit), " ", stringify!($collection))); + assert!( + result.$collection.len() <= $limit, + concat!( + "Expected at most ", + stringify!($limit), + " ", + stringify!($collection) + ) + ); } }; } @@ -543,7 +565,7 @@ macro_rules! output_table_test { ) => { #[rstest] fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; + use $crate::output::{OutputFormat, Outputable}; assert_eq!($fixture.format(OutputFormat::$format), $expected); } }; @@ -556,7 +578,7 @@ macro_rules! output_table_test { ) => { #[rstest] fn $test_name($fixture: $fixture_type) { - use crate::output::Outputable; + use $crate::output::Outputable; assert_eq!($fixture.to_table(), $expected); } }; @@ -575,7 +597,7 @@ macro_rules! output_table_contains_test { ) => { #[rstest] fn $test_name($fixture: $fixture_type) { - use crate::output::Outputable; + use $crate::output::Outputable; let output = $fixture.to_table(); $( assert!(output.contains($needle), concat!("Table output should contain: ", $needle)); @@ -608,7 +630,7 @@ macro_rules! output_json_test { ) => { #[rstest] fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; + use $crate::output::{Outputable, OutputFormat}; let output = $fixture.format(OutputFormat::Json); let parsed: serde_json::Value = serde_json::from_str(&output) .expect("Should produce valid JSON"); @@ -640,7 +662,7 @@ macro_rules! output_toon_test { ) => { #[rstest] fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; + use $crate::output::{Outputable, OutputFormat}; let output = $fixture.format(OutputFormat::Toon); $( assert!(output.contains($needle), concat!("Toon output should contain: ", $needle)); diff --git a/cli/templates/agents/.gitkeep b/cli/templates/agents/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/cli/templates/hooks/.gitkeep b/cli/templates/hooks/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/cli/templates/skills/.gitkeep b/cli/templates/skills/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/db/src/db.rs b/db/src/db.rs index 7958958..354acf3 100644 --- a/db/src/db.rs +++ b/db/src/db.rs @@ -259,20 +259,20 @@ impl CallRowLayout { /// (None) if any required string field cannot be extracted. pub fn extract_call_from_row(row: &[DataValue], layout: &CallRowLayout) -> Option { // Extract caller information - let Some(caller_module) = extract_string(&row[layout.caller_module_idx]) else { return None }; - let Some(caller_name) = extract_string(&row[layout.caller_name_idx]) else { return None }; + let caller_module = extract_string(&row[layout.caller_module_idx])?; + let caller_name = extract_string(&row[layout.caller_name_idx])?; let caller_arity = extract_i64(&row[layout.caller_arity_idx], 0); let caller_kind = extract_string_or(&row[layout.caller_kind_idx], ""); let caller_start_line = extract_i64(&row[layout.caller_start_line_idx], 0); let caller_end_line = extract_i64(&row[layout.caller_end_line_idx], 0); // Extract callee information - let Some(callee_module) = extract_string(&row[layout.callee_module_idx]) else { return None }; - let Some(callee_name) = extract_string(&row[layout.callee_name_idx]) else { return None }; + let callee_module = extract_string(&row[layout.callee_module_idx])?; + let callee_name = extract_string(&row[layout.callee_name_idx])?; let callee_arity = extract_i64(&row[layout.callee_arity_idx], 0); // Extract file and line - let Some(file) = extract_string(&row[layout.file_idx]) else { return None }; + let file = extract_string(&row[layout.file_idx])?; let line = extract_i64(&row[layout.line_idx], 0); // Extract optional call_type diff --git a/db/src/queries/cycles.rs b/db/src/queries/cycles.rs index 47a6105..62568c8 100644 --- a/db/src/queries/cycles.rs +++ b/db/src/queries/cycles.rs @@ -77,11 +77,10 @@ pub fn find_cycle_edges( (row.get(from_idx), row.get(to_idx)) { // Apply module pattern filter if provided - if let Some(pattern) = module_pattern { - if !from.contains(pattern) && !to.contains(pattern) { + if let Some(pattern) = module_pattern + && !from.contains(pattern) && !to.contains(pattern) { continue; } - } edges.push(CycleEdge { from: from.to_string(), to: to.to_string(), diff --git a/db/src/queries/hotspots.rs b/db/src/queries/hotspots.rs index 5f3a94c..71c73ac 100644 --- a/db/src/queries/hotspots.rs +++ b/db/src/queries/hotspots.rs @@ -79,12 +79,11 @@ pub fn get_module_loc( let mut loc_map = std::collections::HashMap::new(); for row in rows.rows { - if row.len() >= 2 { - if let Some(module) = extract_string(&row[0]) { + if row.len() >= 2 + && let Some(module) = extract_string(&row[0]) { let loc = extract_i64(&row[1], 0); loc_map.insert(module, loc); } - } } Ok(loc_map) @@ -130,12 +129,11 @@ pub fn get_function_counts( let mut counts = std::collections::HashMap::new(); for row in rows.rows { - if row.len() >= 2 { - if let Some(module) = extract_string(&row[0]) { + if row.len() >= 2 + && let Some(module) = extract_string(&row[0]) { let count = extract_i64(&row[1], 0); counts.insert(module, count); } - } } Ok(counts) diff --git a/db/src/queries/import.rs b/db/src/queries/import.rs index 9e036f2..dcc7ce0 100644 --- a/db/src/queries/import.rs +++ b/db/src/queries/import.rs @@ -285,7 +285,7 @@ pub fn import_function_locations( let mut rows = Vec::new(); for (module, functions) in &graph.function_locations { - for (_func_key, loc) in functions { + for loc in functions.values() { // Use deserialized fields directly from the JSON let name = &loc.name; let arity = loc.arity; @@ -303,7 +303,7 @@ pub fn import_function_locations( r#"["{}", "{}", "{}", {}, {}, "{}", "{}", {}, "{}", {}, {}, '{}', '{}', "{}", "{}", {}, {}, "{}", "{}"]"#, escaped_project, escape_string(module), - escape_string(&name), + escape_string(name), arity, line, escape_string(loc.file.as_deref().unwrap_or("")), diff --git a/db/src/queries/path.rs b/db/src/queries/path.rs index 503ca63..b602991 100644 --- a/db/src/queries/path.rs +++ b/db/src/queries/path.rs @@ -200,7 +200,7 @@ fn dfs_find_paths( // Check if we reached the target let at_target = current_edge.callee_module == to_module && current_edge.callee_function == to_function - && to_arity.map_or(true, |a| current_edge.callee_arity == a); + && to_arity.is_none_or(|a| current_edge.callee_arity == a); if at_target { // Found a complete path diff --git a/db/src/query_builders.rs b/db/src/query_builders.rs index 0ecca67..6ff2609 100644 --- a/db/src/query_builders.rs +++ b/db/src/query_builders.rs @@ -7,7 +7,9 @@ /// /// # Examples /// -/// ```ignore +/// ``` +/// use db::query_builders::ConditionBuilder; +/// /// let builder = ConditionBuilder::new("module", "module_pattern"); /// let cond = builder.build(false); // "module == $module_pattern" /// let cond = builder.build(true); // "regex_matches(module, $module_pattern)" diff --git a/db/src/types/trace.rs b/db/src/types/trace.rs index 136cc06..e971fc9 100644 --- a/db/src/types/trace.rs +++ b/db/src/types/trace.rs @@ -1,8 +1,6 @@ //! Unified types for trace and reverse-trace commands. -use std::collections::HashMap; use serde::Serialize; -use crate::types::Call; /// Direction of trace traversal #[derive(Debug, Clone, Copy, Default, Serialize)] diff --git a/src/cli.rs b/src/cli.rs deleted file mode 100644 index e4a33b9..0000000 --- a/src/cli.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! CLI argument definitions. -//! -//! This module contains the top-level CLI structure and shared types. -//! Individual command definitions are in the `commands` module. - -use clap::Parser; -use std::path::PathBuf; - -use crate::commands::Command; -use crate::output::OutputFormat; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -pub struct Args { - /// Path to the CozoDB SQLite database file - /// - /// If not specified, searches for database in: - /// 1. .code_search/cozo.sqlite (project-local) - /// 2. ./cozo.sqlite (current directory) - /// 3. ~/.code_search/cozo.sqlite (user-global) - #[arg(long, global = true)] - pub db: Option, - - /// Output format - #[arg(short = 'o', long, value_enum, default_value_t = OutputFormat::Table, global = true)] - pub format: OutputFormat, - - #[command(subcommand)] - pub command: Command, -} - -/// Resolve database path by checking multiple locations in order of preference -pub fn resolve_db_path(explicit_path: Option) -> PathBuf { - // If explicitly specified, use that - if let Some(path) = explicit_path { - return path; - } - - // 1. Check .code_search/cozo.sqlite (project-local) - let project_db = PathBuf::from(".code_search/cozo.sqlite"); - if project_db.exists() { - return project_db; - } - - // 2. Check ./cozo.sqlite (current directory) - let local_db = PathBuf::from("./cozo.sqlite"); - if local_db.exists() { - return local_db; - } - - // 3. Check ~/.code_search/cozo.sqlite (user-global) - if let Some(home_dir) = home::home_dir() { - let global_db = home_dir.join(".code_search/cozo.sqlite"); - if global_db.exists() { - return global_db; - } - } - - // Default: .code_search/cozo.sqlite (will be created if needed) - project_db -} diff --git a/src/commands/accepts/execute.rs b/src/commands/accepts/execute.rs deleted file mode 100644 index ece373c..0000000 --- a/src/commands/accepts/execute.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::AcceptsCmd; -use crate::commands::Execute; -use crate::queries::accepts::{find_accepts, AcceptsEntry}; -use crate::types::ModuleGroupResult; - -/// A function's input type information -#[derive(Debug, Clone, Serialize)] -pub struct AcceptsInfo { - pub name: String, - pub arity: i64, - pub inputs: String, - pub return_type: String, - pub line: i64, -} - -impl ModuleGroupResult { - /// Build grouped result from flat AcceptsEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); - - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let accepts_info = AcceptsInfo { - name: entry.name, - arity: entry.arity, - inputs: entry.inputs_string, - return_type: entry.return_string, - line: entry.line, - }; - (entry.module, accepts_info) - }); - - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } - } -} - -impl Execute for AcceptsCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let entries = find_accepts( - db, - &self.pattern, - &self.common.project, - self.common.regex, - self.module.as_deref(), - self.common.limit, - )?; - - Ok(>::from_entries( - self.pattern, - self.module, - entries, - )) - } -} diff --git a/src/commands/accepts/mod.rs b/src/commands/accepts/mod.rs deleted file mode 100644 index 7e7c191..0000000 --- a/src/commands/accepts/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions accepting a specific type pattern -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search accepts \"User.t\" # Find functions accepting User.t - code_search accepts \"map()\" # Find functions accepting maps - code_search accepts \"User.t\" MyApp # Filter to module MyApp - code_search accepts -r \"list\\(.*\\)\" # Regex pattern matching -")] -pub struct AcceptsCmd { - /// Type pattern to search for in input types - pub pattern: String, - - /// Module filter pattern - pub module: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for AcceptsCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/accepts/output.rs b/src/commands/accepts/output.rs deleted file mode 100644 index 9d7e44a..0000000 --- a/src/commands/accepts/output.rs +++ /dev/null @@ -1,33 +0,0 @@ -//! Output formatting for accepts command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::AcceptsInfo; - -impl TableFormatter for ModuleGroupResult { - type Entry = AcceptsInfo; - - fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); - format!("Functions accepting \"{}\"", pattern) - } - - fn format_empty_message(&self) -> String { - "No functions found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} function(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, accepts_info: &AcceptsInfo, _module: &str, _file: &str) -> String { - format!( - "{}/{} ({}) → {}", - accepts_info.name, accepts_info.arity, accepts_info.inputs, accepts_info.return_type - ) - } -} diff --git a/src/commands/boundaries/execute.rs b/src/commands/boundaries/execute.rs deleted file mode 100644 index 20120a6..0000000 --- a/src/commands/boundaries/execute.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::BoundariesCmd; -use crate::commands::Execute; -use crate::queries::hotspots::{find_hotspots, HotspotKind}; -use crate::types::{ModuleCollectionResult, ModuleGroup}; - -/// A single boundary module entry -#[derive(Debug, Clone, Serialize)] -pub struct BoundaryEntry { - pub incoming: i64, - pub outgoing: i64, - pub ratio: f64, -} - -impl Execute for BoundariesCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let hotspots = find_hotspots( - db, - HotspotKind::Ratio, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.common.limit, - false, - true, // require_outgoing: exclude leaf nodes - )?; - - // Build module groups, filtering by thresholds and deduplicating by module - let mut seen_modules = std::collections::HashSet::new(); - let mut items = Vec::new(); - - for hotspot in hotspots { - // Boundaries must have both incoming AND outgoing calls - // (leaf modules with only incoming calls are not boundaries) - if hotspot.incoming >= self.min_incoming - && hotspot.outgoing >= 1 - && hotspot.ratio >= self.min_ratio - && seen_modules.insert(hotspot.module.clone()) - { - items.push(ModuleGroup { - name: hotspot.module, - file: String::new(), - entries: vec![BoundaryEntry { - incoming: hotspot.incoming, - outgoing: hotspot.outgoing, - ratio: hotspot.ratio, - }], - function_count: None, - }); - } - } - - let total_items = items.len(); - - Ok(ModuleCollectionResult { - module_pattern: self.module.unwrap_or_else(|| "*".to_string()), - function_pattern: None, - kind_filter: Some("boundary".to_string()), - name_filter: None, - total_items, - items, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rstest::fixture; - use tempfile::NamedTempFile; - - #[fixture] - fn test_db() -> NamedTempFile { - NamedTempFile::new().unwrap() - } - - #[test] - fn test_boundaries_execute_creates_result_with_boundary_kind() { - // This test verifies the execute method creates a result with kind_filter set to "boundary" - // Full integration tests would require a real database with call graph data - // For now, we test the structure and defaults - let _cmd = BoundariesCmd { - min_incoming: 5, - min_ratio: 2.0, - module: None, - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 50, - }, - }; - - // The execute method would call find_hotspots and filter results - // We verify the command struct is created correctly - assert_eq!(_cmd.min_incoming, 5); - assert_eq!(_cmd.min_ratio, 2.0); - } -} diff --git a/src/commands/boundaries/mod.rs b/src/commands/boundaries/mod.rs deleted file mode 100644 index 7f4e01b..0000000 --- a/src/commands/boundaries/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find boundary modules - modules with high fan-in but low fan-out -/// -/// Boundary modules are those that many other modules depend on but have few -/// dependencies themselves. They are identified by high ratio of incoming to -/// outgoing calls, indicating they are central points in the architecture. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search boundaries # Find all boundary modules - code_search boundaries MyApp.Web # Filter to MyApp.Web namespace - code_search boundaries --min-incoming 5 # With minimum 5 incoming calls - code_search boundaries --min-ratio 2.0 # With minimum 2.0 ratio - code_search boundaries -l 20 # Show top 20 boundary modules -")] -pub struct BoundariesCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Minimum incoming calls to be considered a boundary module - #[arg(long, default_value = "1")] - pub min_incoming: i64, - - /// Minimum ratio (incoming/outgoing) to be considered a boundary module - #[arg(long, default_value = "2.0")] - pub min_ratio: f64, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for BoundariesCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/boundaries/output.rs b/src/commands/boundaries/output.rs deleted file mode 100644 index 8dc4139..0000000 --- a/src/commands/boundaries/output.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Output formatting for boundaries command results. - -use super::execute::BoundaryEntry; -use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; - -impl TableFormatter for ModuleCollectionResult { - type Entry = BoundaryEntry; - - fn format_header(&self) -> String { - let filter_info = if self.module_pattern != "*" { - format!(" (module: {})", self.module_pattern) - } else { - String::new() - }; - format!("Boundary Modules{}", filter_info) - } - - fn format_empty_message(&self) -> String { - "No boundary modules found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} boundary module(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_module_header_with_entries( - &self, - module_name: &str, - _module_file: &str, - entries: &[BoundaryEntry], - ) -> String { - if entries.is_empty() { - return format!("{}:", module_name); - } - - // Get the first (and typically only) entry for module-level stats - let entry = &entries[0]; - - // Format ratio with special case for infinite (outgoing = 0) - let ratio_str = if entry.outgoing == 0 { - "∞".to_string() - } else { - format!("{:.1}", entry.ratio) - }; - - format!( - "{}: (in: {}, out: {}, ratio: {})", - module_name, entry.incoming, entry.outgoing, ratio_str - ) - } - - fn format_entry(&self, entry: &BoundaryEntry, _module: &str, _file: &str) -> String { - // For boundaries, we don't show individual entries since there's only one per module - // But if there are multiple, format them - let ratio_str = if entry.outgoing == 0 { - "∞".to_string() - } else { - format!("{:.1}", entry.ratio) - }; - - format!( - "(in: {}, out: {}, ratio: {})", - entry.incoming, entry.outgoing, ratio_str - ) - } - - fn blank_before_module(&self) -> bool { - true - } - - fn blank_after_summary(&self) -> bool { - false - } -} diff --git a/src/commands/browse_module/cli_tests.rs b/src/commands/browse_module/cli_tests.rs deleted file mode 100644 index fbe1f4b..0000000 --- a/src/commands/browse_module/cli_tests.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! CLI parsing tests for browse-module command. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use crate::commands::browse_module::DefinitionKind; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - // Positional argument test - browse-module requires a module or file argument - #[test] - fn test_requires_module_or_file() { - let result = Args::try_parse_from(["code_search", "browse-module"]); - assert!(result.is_err(), "Should require module_or_file positional argument"); - } - - crate::cli_option_test! { - command: "browse-module", - variant: BrowseModule, - test_name: test_with_module_name, - args: ["MyApp.Accounts"], - field: module_or_file, - expected: "MyApp.Accounts", - } - - crate::cli_option_test! { - command: "browse-module", - variant: BrowseModule, - test_name: test_with_file_path, - args: ["lib/accounts.ex"], - field: module_or_file, - expected: "lib/accounts.ex", - } - - crate::cli_option_test! { - command: "browse-module", - variant: BrowseModule, - test_name: test_with_regex, - args: ["MyApp.*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "browse-module", - variant: BrowseModule, - test_name: test_with_name_filter, - args: ["MyApp.Accounts", "--name", "get_user"], - field: name, - expected: Some("get_user".to_string()), - } - - crate::cli_option_test! { - command: "browse-module", - variant: BrowseModule, - test_name: test_with_limit, - args: ["MyApp.Accounts", "--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_limit_tests! { - command: "browse-module", - variant: BrowseModule, - required_args: ["MyApp.Accounts"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Kind filter tests (manual - enum variant) - // ========================================================================= - - #[rstest] - #[case("functions", DefinitionKind::Functions)] - #[case("specs", DefinitionKind::Specs)] - #[case("types", DefinitionKind::Types)] - #[case("structs", DefinitionKind::Structs)] - fn test_kind_filter(#[case] kind_str: &str, #[case] expected: DefinitionKind) { - let args = Args::try_parse_from([ - "code_search", - "browse-module", - "MyApp.Accounts", - "--kind", - kind_str, - ]) - .expect("Failed to parse args"); - - if let crate::commands::Command::BrowseModule(cmd) = args.command { - assert!(cmd.kind.is_some()); - assert!(matches!(cmd.kind.unwrap(), k if std::mem::discriminant(&k) == std::mem::discriminant(&expected))); - } else { - panic!("Expected BrowseModule command"); - } - } - - #[test] - fn test_kind_filter_default_is_none() { - let args = Args::try_parse_from(["code_search", "browse-module", "MyApp.Accounts"]) - .expect("Failed to parse args"); - - if let crate::commands::Command::BrowseModule(cmd) = args.command { - assert!(cmd.kind.is_none()); - } else { - panic!("Expected BrowseModule command"); - } - } -} diff --git a/src/commands/browse_module/execute.rs b/src/commands/browse_module/execute.rs deleted file mode 100644 index d239845..0000000 --- a/src/commands/browse_module/execute.rs +++ /dev/null @@ -1,325 +0,0 @@ -use std::cmp::Ordering; -use std::error::Error; - -use serde::Serialize; - -use super::{BrowseModuleCmd, DefinitionKind}; -use crate::commands::Execute; -use crate::queries::file::find_functions_in_module; -use crate::queries::specs::find_specs; -use crate::queries::types::find_types; -use crate::queries::structs::{find_struct_fields, group_fields_into_structs, FieldInfo}; - -/// Result of browsing definitions in a module -#[derive(Debug, Serialize)] -pub struct BrowseModuleResult { - /// The module name or file pattern that was searched - pub search_term: String, - - /// The definition kind filter applied (if any) - #[serde(skip_serializing_if = "Option::is_none")] - pub kind_filter: Option, - - /// Project that was searched - pub project: String, - - /// Total number of definitions found (before limit applied) - pub total_items: usize, - - /// All matching definitions, flattened array with type discriminant - pub definitions: Vec, -} - -/// A single definition from any category (function, spec, type, or struct) -/// -/// Uses serde(tag = "type") to add a discriminant field to JSON output, -/// making it easy for consumers to identify the definition type. -#[derive(Debug, Clone, Serialize)] -#[serde(tag = "type")] -#[serde(rename_all = "lowercase")] -pub enum Definition { - /// A function definition with location and signature - Function { - module: String, - #[serde(skip_serializing_if = "String::is_empty")] - file: String, - name: String, - arity: i64, - line: i64, - start_line: i64, - end_line: i64, - kind: String, - #[serde(skip_serializing_if = "String::is_empty")] - args: String, - #[serde(skip_serializing_if = "String::is_empty")] - return_type: String, - #[serde(skip_serializing_if = "String::is_empty")] - pattern: String, - #[serde(skip_serializing_if = "String::is_empty")] - guard: String, - }, - - /// A spec definition (@spec or @callback) - Spec { - module: String, - name: String, - arity: i64, - line: i64, - kind: String, - #[serde(skip_serializing_if = "String::is_empty")] - inputs: String, - #[serde(skip_serializing_if = "String::is_empty")] - returns: String, - #[serde(skip_serializing_if = "String::is_empty")] - full: String, - }, - - /// A type definition (@type, @typep, or @opaque) - Type { - module: String, - name: String, - line: i64, - kind: String, - #[serde(skip_serializing_if = "String::is_empty")] - params: String, - #[serde(skip_serializing_if = "String::is_empty")] - definition: String, - }, - - /// A struct definition with fields - Struct { - module: String, - name: String, - fields: Vec, - }, -} - -impl Definition { - /// Get the module name for this definition - pub fn module(&self) -> &str { - match self { - Definition::Function { module, .. } => module, - Definition::Spec { module, .. } => module, - Definition::Type { module, .. } => module, - Definition::Struct { module, .. } => module, - } - } - - /// Get the line number for this definition - pub fn line(&self) -> i64 { - match self { - Definition::Function { line, .. } => *line, - Definition::Spec { line, .. } => *line, - Definition::Type { line, .. } => *line, - Definition::Struct { .. } => 0, // Structs don't have a single line - } - } -} - -impl Execute for BrowseModuleCmd { - type Output = BrowseModuleResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let mut definitions = Vec::new(); - - // Determine what to query based on kind filter - let should_query_functions = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Functions)); - let should_query_specs = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Specs)); - let should_query_types = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Types)); - let should_query_structs = self.kind.is_none() || matches!(self.kind, Some(DefinitionKind::Structs)); - - // Query functions (from function_locations table for file + line info) - if should_query_functions { - let funcs = find_functions_in_module( - db, - &self.module_or_file, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - for func in funcs { - // Filter by name if specified - if let Some(ref name_filter) = self.name { - if !func.name.contains(name_filter) { - continue; - } - } - - definitions.push(Definition::Function { - module: func.module, - file: func.file, - name: func.name, - arity: func.arity, - line: func.line, - start_line: func.start_line, - end_line: func.end_line, - kind: func.kind, - args: String::new(), // Not in function_locations - return_type: String::new(), // Not in function_locations - pattern: func.pattern, - guard: func.guard, - }); - } - } - - // Query specs - if should_query_specs { - let specs = find_specs( - db, - &self.module_or_file, - self.name.as_deref(), - None, // kind filter (optional, not used for browse) - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - for spec in specs { - definitions.push(Definition::Spec { - module: spec.module, - name: spec.name, - arity: spec.arity, - line: spec.line, - kind: spec.kind, - inputs: spec.inputs_string, - returns: spec.return_string, - full: spec.full, - }); - } - } - - // Query types - if should_query_types { - let types = find_types( - db, - &self.module_or_file, - self.name.as_deref(), - None, // kind filter (optional, not used for browse) - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - for type_def in types { - definitions.push(Definition::Type { - module: type_def.module, - name: type_def.name, - line: type_def.line, - kind: type_def.kind, - params: type_def.params, - definition: type_def.definition, - }); - } - } - - // Query structs - if should_query_structs { - let fields = find_struct_fields(db, &self.module_or_file, &self.common.project, self.common.regex, self.common.limit)?; - let structs = group_fields_into_structs(fields); - - for struct_def in structs { - // Filter by name if specified - if let Some(ref name_filter) = self.name { - if !struct_def.module.contains(name_filter) { - continue; - } - } - - definitions.push(Definition::Struct { - module: struct_def.module.clone(), - name: struct_def.module.clone(), // Struct name is same as module for now - fields: struct_def.fields, - }); - } - } - - // Sort by module, then by line number - definitions.sort_by(|a, b| { - match a.module().cmp(b.module()) { - Ordering::Equal => a.line().cmp(&b.line()), - other => other, - } - }); - - let total_items = definitions.len(); - - // Apply limit - definitions.truncate(self.common.limit as usize); - - Ok(BrowseModuleResult { - search_term: self.module_or_file, - kind_filter: self.kind, - project: self.common.project, - total_items, - definitions, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_definition_sort_order() { - let defs = vec![ - Definition::Function { - module: "B".to_string(), - file: String::new(), - name: "f".to_string(), - arity: 0, - line: 10, - start_line: 10, - end_line: 10, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - Definition::Function { - module: "A".to_string(), - file: String::new(), - name: "f".to_string(), - arity: 0, - line: 20, - start_line: 20, - end_line: 20, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - Definition::Function { - module: "A".to_string(), - file: String::new(), - name: "f".to_string(), - arity: 0, - line: 5, - start_line: 5, - end_line: 5, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - ]; - - let mut sorted = defs.clone(); - sorted.sort_by(|a, b| match a.module().cmp(b.module()) { - Ordering::Equal => a.line().cmp(&b.line()), - other => other, - }); - - // Should be: A/5, A/20, B/10 - assert_eq!(sorted[0].module(), "A"); - assert_eq!(sorted[0].line(), 5); - assert_eq!(sorted[1].module(), "A"); - assert_eq!(sorted[1].line(), 20); - assert_eq!(sorted[2].module(), "B"); - assert_eq!(sorted[2].line(), 10); - } -} diff --git a/src/commands/browse_module/execute_tests.rs b/src/commands/browse_module/execute_tests.rs deleted file mode 100644 index 61041db..0000000 --- a/src/commands/browse_module/execute_tests.rs +++ /dev/null @@ -1,323 +0,0 @@ -//! Execute tests for browse-module command. - -#[cfg(test)] -mod tests { - use super::super::{BrowseModuleCmd, DefinitionKind}; - use super::super::execute::Definition; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Fixtures - call_graph has functions, specs, and types - // ========================================================================= - - crate::shared_fixture! { - fixture_name: call_graph_db, - fixture_type: call_graph, - project: "test_project", - } - - crate::shared_fixture! { - fixture_name: structs_db, - fixture_type: structs, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - Functions - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_finds_functions, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: Some(DefinitionKind::Functions), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(!result.definitions.is_empty()); - // All definitions should be functions - for def in &result.definitions { - assert!(matches!(def, Definition::Function { .. })); - } - // MyApp.Accounts has: get_user/1, get_user/2, list_users/0, validate_email/1 - assert_eq!(result.definitions.len(), 4); - }, - } - - crate::execute_test! { - test_name: test_browse_module_with_name_filter, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: Some(DefinitionKind::Functions), - name: Some("get_user".to_string()), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // Only get_user/1 and get_user/2 should match - assert_eq!(result.definitions.len(), 2); - for def in &result.definitions { - if let Definition::Function { name, .. } = def { - assert!(name.contains("get_user")); - } - } - }, - } - - // ========================================================================= - // Core functionality tests - Specs - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_finds_specs, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: Some(DefinitionKind::Specs), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(!result.definitions.is_empty()); - // All definitions should be specs - for def in &result.definitions { - assert!(matches!(def, Definition::Spec { .. })); - } - // MyApp.Accounts has specs for: get_user/1, list_users/0 - assert_eq!(result.definitions.len(), 2); - }, - } - - // ========================================================================= - // Core functionality tests - Types - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_finds_types, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: Some(DefinitionKind::Types), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(!result.definitions.is_empty()); - // All definitions should be types - for def in &result.definitions { - assert!(matches!(def, Definition::Type { .. })); - } - // MyApp.Accounts has types: user (type), user_id (opaque) - assert_eq!(result.definitions.len(), 2); - }, - } - - // ========================================================================= - // Core functionality tests - Structs - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_finds_structs, - fixture: structs_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.User".to_string(), - kind: Some(DefinitionKind::Structs), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.definitions.len(), 1); - if let Definition::Struct { name, fields, .. } = &result.definitions[0] { - assert_eq!(name, "MyApp.User"); - // User has: id, name, email, admin, inserted_at - assert_eq!(fields.len(), 5); - } else { - panic!("Expected struct definition"); - } - }, - } - - // ========================================================================= - // Core functionality tests - All kinds (no filter) - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_all_kinds, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: None, // No kind filter - get all - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // Should have functions, specs, and types - let has_functions = result.definitions.iter().any(|d| matches!(d, Definition::Function { .. })); - let has_specs = result.definitions.iter().any(|d| matches!(d, Definition::Spec { .. })); - let has_types = result.definitions.iter().any(|d| matches!(d, Definition::Type { .. })); - - assert!(has_functions, "Should have functions"); - assert!(has_specs, "Should have specs"); - assert!(has_types, "Should have types"); - - // Functions: 4, Specs: 2, Types: 2 = 8 total - assert_eq!(result.total_items, 8); - }, - } - - // ========================================================================= - // Regex pattern tests - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_regex_pattern, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp\\..*".to_string(), - kind: Some(DefinitionKind::Functions), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - // Should find functions from all MyApp.* modules - assert!(!result.definitions.is_empty()); - // Total functions across all modules in fixture: - // Controller: 3, Accounts: 4, Service: 3, Repo: 3, Notifier: 2 = 15 - assert_eq!(result.definitions.len(), 15); - }, - } - - // ========================================================================= - // Sort order tests - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_sorted_by_module_then_line, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp\\..*".to_string(), - kind: Some(DefinitionKind::Functions), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - // Verify sorted by module then by line - let mut prev_module = String::new(); - let mut prev_line: i64 = 0; - - for def in &result.definitions { - let (module, line) = match def { - Definition::Function { module, line, .. } => (module.clone(), *line), - _ => continue, - }; - - if module == prev_module { - assert!(line >= prev_line, "Within same module, lines should be ascending"); - } else if !prev_module.is_empty() { - assert!(module >= prev_module, "Modules should be in alphabetical order"); - } - - prev_module = module; - prev_line = line; - } - }, - } - - // ========================================================================= - // Limit tests - // ========================================================================= - - crate::execute_test! { - test_name: test_browse_module_with_limit, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "MyApp\\..*".to_string(), - kind: Some(DefinitionKind::Functions), - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 5, - }, - }, - assertions: |result| { - // Should respect limit - assert_eq!(result.definitions.len(), 5); - // total_items should reflect actual count before limit - assert!(result.total_items >= 5); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_browse_module_no_match, - fixture: call_graph_db, - cmd: BrowseModuleCmd { - module_or_file: "NonExistent.Module".to_string(), - kind: None, - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: definitions, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: BrowseModuleCmd, - cmd: BrowseModuleCmd { - module_or_file: "MyApp.Accounts".to_string(), - kind: None, - name: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/browse_module/mod.rs b/src/commands/browse_module/mod.rs deleted file mode 100644 index 791f378..0000000 --- a/src/commands/browse_module/mod.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::error::Error; - -use clap::{Parser, ValueEnum}; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; -use serde::Serialize; - -mod cli_tests; -pub mod execute; -mod execute_tests; -pub mod output; -mod output_tests; - -/// Browse definitions in a module or file -/// -/// Unified command to explore all definitions (functions, specs, types, structs) -/// in a given module or file pattern. Returns all matching definitions grouped -/// and sorted by module and line number. -#[derive(Parser, Debug)] -pub struct BrowseModuleCmd { - /// Module name, pattern, or file path to browse - /// - /// Can be: - /// - Module name: "MyApp.Accounts" (exact match or pattern) - /// - File path: "lib/accounts.ex" (substring or regex with --regex) - /// - Pattern: "MyApp.*" (with --regex) - pub module_or_file: String, - - /// Type of definitions to show - /// - /// If omitted, shows all definition types (functions, specs, types, structs). - /// If specified, filters to only that type. - #[arg(short, long)] - pub kind: Option, - - /// Filter by definition name (function/type/spec/struct name) - /// - /// Applies across all definition types. Supports substring match by default - /// or regex match with --regex. - #[arg(short, long)] - pub name: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -/// Type of definition to filter by -#[derive(Debug, Clone, Copy, ValueEnum, Serialize)] -#[serde(rename_all = "lowercase")] -pub enum DefinitionKind { - /// Function definitions - Functions, - /// @spec and @callback definitions - Specs, - /// @type, @typep, @opaque definitions - Types, - /// Struct definitions with fields - Structs, -} - -impl std::fmt::Display for DefinitionKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - DefinitionKind::Functions => write!(f, "functions"), - DefinitionKind::Specs => write!(f, "specs"), - DefinitionKind::Types => write!(f, "types"), - DefinitionKind::Structs => write!(f, "structs"), - } - } -} - -impl CommandRunner for BrowseModuleCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/browse_module/output.rs b/src/commands/browse_module/output.rs deleted file mode 100644 index 869a53b..0000000 --- a/src/commands/browse_module/output.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::collections::BTreeMap; - -use super::execute::{BrowseModuleResult, Definition}; -use crate::output::Outputable; -use crate::utils::format_type_definition; - -impl Outputable for BrowseModuleResult { - fn to_table(&self) -> String { - let mut output = String::new(); - - // Header - if let Some(kind) = self.kind_filter { - output.push_str(&format!( - "Definitions in {} (kind: {}, project: {})\n\n", - self.search_term, kind, self.project - )); - } else { - output.push_str(&format!( - "Definitions in {} (project: {})\n\n", - self.search_term, self.project - )); - } - - // Empty state - if self.definitions.is_empty() { - output.push_str("No definitions found.\n"); - return output; - } - - // Summary - output.push_str(&format!( - "Found {} definition(s):\n\n", - self.total_items - )); - - // Group by module for readability - let mut by_module: BTreeMap> = BTreeMap::new(); - for def in &self.definitions { - by_module - .entry(def.module().to_string()) - .or_insert_with(Vec::new) - .push(def); - } - - // Format each module and its definitions - for (module, definitions) in by_module { - output.push_str(&format!(" {}:\n", module)); - - for def in definitions { - match def { - Definition::Function { - name, - arity, - start_line, - end_line, - kind, - args, - return_type, - .. - } => { - output.push_str(&format!(" L{}-{} [{}] {}/{}\n", start_line, end_line, kind, name, arity)); - if !args.is_empty() || !return_type.is_empty() { - output.push_str(&format!(" {} {}\n", args, return_type).trim_end()); - output.push('\n'); - } - } - - Definition::Spec { - name, - arity, - line, - kind, - full, - .. - } => { - output.push_str(&format!(" L{:<3} [{}] {}/{}\n", line, kind, name, arity)); - if !full.is_empty() { - output.push_str(&format!(" {}\n", full)); - } - } - - Definition::Type { - name, - line, - kind, - definition, - .. - } => { - output.push_str(&format!(" L{:<3} [{}] {}\n", line, kind, name)); - if !definition.is_empty() { - let formatted = format_type_definition(definition); - // Indent multi-line definitions properly - for (i, def_line) in formatted.lines().enumerate() { - if i == 0 { - output.push_str(&format!(" {}\n", def_line)); - } else { - output.push_str(&format!(" {}\n", def_line)); - } - } - } - } - - Definition::Struct { name, fields, .. } => { - output.push_str(&format!(" [struct] {} with {} fields\n", name, fields.len())); - for field in fields.iter() { - output.push_str(&format!( - " - {}: {} {}\n", - field.name, - field.inferred_type, - if field.required { "(required)" } else { "(optional)" } - )); - } - } - } - } - - output.push('\n'); - } - - output - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_empty_result() { - let result = BrowseModuleResult { - search_term: "NonExistent".to_string(), - kind_filter: None, - project: "default".to_string(), - total_items: 0, - definitions: vec![], - }; - - let table = result.to_table(); - assert!(table.contains("No definitions found")); - } - - #[test] - fn test_function_formatting() { - use super::super::execute::Definition; - - let result = BrowseModuleResult { - search_term: "MyApp.Accounts".to_string(), - kind_filter: None, - project: "default".to_string(), - total_items: 1, - definitions: vec![Definition::Function { - module: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - name: "get_user".to_string(), - arity: 1, - line: 10, - start_line: 10, - end_line: 20, - kind: "def".to_string(), - args: "(integer())".to_string(), - return_type: "User.t() | nil".to_string(), - pattern: String::new(), - guard: String::new(), - }], - }; - - let table = result.to_table(); - assert!(table.contains("MyApp.Accounts")); - assert!(table.contains("get_user/1")); - assert!(table.contains("[def]")); - assert!(table.contains("L10-20")); - } - - #[test] - fn test_mixed_types_formatting() { - use super::super::execute::Definition; - - let result = BrowseModuleResult { - search_term: "MyApp.Accounts".to_string(), - kind_filter: None, - project: "default".to_string(), - total_items: 2, - definitions: vec![ - Definition::Function { - module: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - name: "get_user".to_string(), - arity: 1, - line: 10, - start_line: 10, - end_line: 20, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - Definition::Type { - module: "MyApp.Accounts".to_string(), - name: "user".to_string(), - line: 5, - kind: "type".to_string(), - params: String::new(), - definition: "@type user() :: %{}".to_string(), - }, - ], - }; - - let table = result.to_table(); - assert!(table.contains("MyApp.Accounts")); - assert!(table.contains("[def]")); - assert!(table.contains("[type]")); - assert!(table.contains("Found 2 definition(s)")); - } -} diff --git a/src/commands/browse_module/output_tests.rs b/src/commands/browse_module/output_tests.rs deleted file mode 100644 index 2790b4a..0000000 --- a/src/commands/browse_module/output_tests.rs +++ /dev/null @@ -1,261 +0,0 @@ -//! Output formatting tests for browse-module command. - -#[cfg(test)] -mod tests { - use super::super::execute::{BrowseModuleResult, Definition}; - use super::super::DefinitionKind; - use crate::queries::structs::FieldInfo; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Definitions in NonExistent (project: default) - -No definitions found. -"; - - const FUNCTIONS_ONLY_TABLE: &str = "\ -Definitions in MyApp.Accounts (kind: functions, project: default) - -Found 2 definition(s): - - MyApp.Accounts: - L10-15 [def] get_user/1 - L24-28 [def] list_users/0 - -"; - - const MIXED_TYPES_TABLE: &str = "\ -Definitions in MyApp.Accounts (project: default) - -Found 3 definition(s): - - MyApp.Accounts: - L5 [type] user - @type user() :: %{id: integer()} - L8 [spec] get_user/1 - @spec get_user(integer()) :: User.t() - L10-15 [def] get_user/1 - -"; - - const STRUCT_TABLE: &str = "\ -Definitions in MyApp.User (kind: structs, project: default) - -Found 1 definition(s): - - MyApp.User: - [struct] MyApp.User with 2 fields - - id: integer() (required) - - name: String.t() (optional) - -"; - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> BrowseModuleResult { - BrowseModuleResult { - search_term: "NonExistent".to_string(), - kind_filter: None, - project: "default".to_string(), - total_items: 0, - definitions: vec![], - } - } - - #[fixture] - fn functions_only_result() -> BrowseModuleResult { - BrowseModuleResult { - search_term: "MyApp.Accounts".to_string(), - kind_filter: Some(DefinitionKind::Functions), - project: "default".to_string(), - total_items: 2, - definitions: vec![ - Definition::Function { - module: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - name: "get_user".to_string(), - arity: 1, - line: 10, - start_line: 10, - end_line: 15, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - Definition::Function { - module: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - name: "list_users".to_string(), - arity: 0, - line: 24, - start_line: 24, - end_line: 28, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - ], - } - } - - #[fixture] - fn mixed_types_result() -> BrowseModuleResult { - // Definitions are sorted by module then line - so L5, L8, L10 - BrowseModuleResult { - search_term: "MyApp.Accounts".to_string(), - kind_filter: None, - project: "default".to_string(), - total_items: 3, - definitions: vec![ - Definition::Type { - module: "MyApp.Accounts".to_string(), - name: "user".to_string(), - line: 5, - kind: "type".to_string(), - params: String::new(), - definition: "@type user() :: %{id: integer()}".to_string(), - }, - Definition::Spec { - module: "MyApp.Accounts".to_string(), - name: "get_user".to_string(), - arity: 1, - line: 8, - kind: "spec".to_string(), - inputs: "integer()".to_string(), - returns: "User.t()".to_string(), - full: "@spec get_user(integer()) :: User.t()".to_string(), - }, - Definition::Function { - module: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - name: "get_user".to_string(), - arity: 1, - line: 10, - start_line: 10, - end_line: 15, - kind: "def".to_string(), - args: String::new(), - return_type: String::new(), - pattern: String::new(), - guard: String::new(), - }, - ], - } - } - - #[fixture] - fn struct_result() -> BrowseModuleResult { - BrowseModuleResult { - search_term: "MyApp.User".to_string(), - kind_filter: Some(DefinitionKind::Structs), - project: "default".to_string(), - total_items: 1, - definitions: vec![Definition::Struct { - module: "MyApp.User".to_string(), - name: "MyApp.User".to_string(), - fields: vec![ - FieldInfo { - name: "id".to_string(), - inferred_type: "integer()".to_string(), - default_value: "nil".to_string(), - required: true, - }, - FieldInfo { - name: "name".to_string(), - inferred_type: "String.t()".to_string(), - default_value: "nil".to_string(), - required: false, - }, - ], - }], - } - } - - // ========================================================================= - // Table format tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: BrowseModuleResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_functions_only, - fixture: functions_only_result, - fixture_type: BrowseModuleResult, - expected: FUNCTIONS_ONLY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_mixed_types, - fixture: mixed_types_result, - fixture_type: BrowseModuleResult, - expected: MIXED_TYPES_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_struct, - fixture: struct_result, - fixture_type: BrowseModuleResult, - expected: STRUCT_TABLE, - } - - // ========================================================================= - // JSON format tests - // ========================================================================= - - #[rstest] - fn test_json_format_contains_type_discriminant(functions_only_result: BrowseModuleResult) { - use crate::output::{OutputFormat, Outputable}; - - let json = functions_only_result.format(OutputFormat::Json); - - // Verify the type tag is present for each definition - assert!(json.contains("\"type\": \"function\"")); - } - - #[rstest] - fn test_json_format_struct_contains_fields(struct_result: BrowseModuleResult) { - use crate::output::{OutputFormat, Outputable}; - - let json = struct_result.format(OutputFormat::Json); - - assert!(json.contains("\"type\": \"struct\"")); - assert!(json.contains("\"fields\"")); - assert!(json.contains("\"id\"")); - assert!(json.contains("\"name\"")); - } - - // ========================================================================= - // Toon format tests - // ========================================================================= - - #[rstest] - fn test_toon_format_compact(functions_only_result: BrowseModuleResult) { - use crate::output::{OutputFormat, Outputable}; - - let toon = functions_only_result.format(OutputFormat::Toon); - - // Toon format should be more compact than JSON - let json = functions_only_result.format(OutputFormat::Json); - assert!(toon.len() < json.len(), "Toon should be more compact than JSON"); - - // Should contain key information - assert!(toon.contains("MyApp.Accounts")); - assert!(toon.contains("get_user")); - } -} diff --git a/src/commands/calls_from/cli_tests.rs b/src/commands/calls_from/cli_tests.rs deleted file mode 100644 index bda1917..0000000 --- a/src/commands/calls_from/cli_tests.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! CLI parsing tests for calls-from command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_required_arg_test! { - command: "calls-from", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_option_test! { - command: "calls-from", - variant: CallsFrom, - test_name: test_with_module, - args: ["MyApp.Accounts"], - field: module, - expected: "MyApp.Accounts", - } - - crate::cli_option_test! { - command: "calls-from", - variant: CallsFrom, - test_name: test_with_function, - args: ["MyApp.Accounts", "get_user"], - field: function, - expected: Some("get_user".to_string()), - } - - crate::cli_option_test! { - command: "calls-from", - variant: CallsFrom, - test_name: test_with_arity, - args: ["MyApp.Accounts", "get_user", "1"], - field: arity, - expected: Some(1), - } - - crate::cli_option_test! { - command: "calls-from", - variant: CallsFrom, - test_name: test_with_regex, - args: ["MyApp.*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "calls-from", - variant: CallsFrom, - test_name: test_with_limit, - args: ["MyApp.Accounts", "--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_limit_tests! { - command: "calls-from", - variant: CallsFrom, - required_args: ["MyApp.Accounts"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/calls_from/execute.rs b/src/commands/calls_from/execute.rs deleted file mode 100644 index 873afb9..0000000 --- a/src/commands/calls_from/execute.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::CallsFromCmd; -use crate::commands::Execute; -use crate::queries::calls_from::find_calls_from; -use crate::types::{Call, ModuleGroupResult}; -use crate::utils::group_calls; - -/// A caller function with all its outgoing calls -#[derive(Debug, Clone, Serialize)] -pub struct CallerFunction { - pub name: String, - pub arity: i64, - pub kind: String, - pub start_line: i64, - pub end_line: i64, - pub calls: Vec, -} - -impl ModuleGroupResult { - /// Build grouped result from flat calls - pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { - let (total_items, items) = group_calls( - calls, - // Group by caller module - |call| call.caller.module.to_string(), - // Key by caller function metadata - |call| CallerFunctionKey { - name: call.caller.name.to_string(), - arity: call.caller.arity, - kind: call.caller.kind.as_deref().unwrap_or("").to_string(), - start_line: call.caller.start_line.unwrap_or(0), - end_line: call.caller.end_line.unwrap_or(0), - }, - // Sort by line number - |a, b| a.line.cmp(&b.line), - // Deduplicate by callee (module, name, arity) - |c| (c.callee.module.to_string(), c.callee.name.to_string(), c.callee.arity), - // Build CallerFunction entry - |key, calls| CallerFunction { - name: key.name, - arity: key.arity, - kind: key.kind, - start_line: key.start_line, - end_line: key.end_line, - calls, - }, - // File tracking strategy: extract from first call in first function - |_module, functions_map| { - functions_map - .values() - .next() - .and_then(|calls| calls.first()) - .and_then(|call| call.caller.file.as_deref()) - .unwrap_or("") - .to_string() - }, - ); - - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } - } -} - -/// Key for grouping by caller function (used internally) -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct CallerFunctionKey { - name: String, - arity: i64, - kind: String, - start_line: i64, - end_line: i64, -} - -impl Execute for CallsFromCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let calls = find_calls_from( - db, - &self.module, - self.function.as_deref(), - self.arity, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(>::from_calls( - self.module, - self.function.unwrap_or_default(), - calls, - )) - } -} diff --git a/src/commands/calls_from/execute_tests.rs b/src/commands/calls_from/execute_tests.rs deleted file mode 100644 index cda895b..0000000 --- a/src/commands/calls_from/execute_tests.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! Execute tests for calls-from command. - -#[cfg(test)] -mod tests { - use super::super::CallsFromCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // MyApp.Accounts has 3 call records: get_user/1→Repo.get, get_user/2→Repo.get, list_users→Repo.all - // Per-function deduplication: each function keeps its unique callees = 3 calls displayed - crate::execute_test! { - test_name: test_calls_from_module, - fixture: populated_db, - cmd: CallsFromCmd { - module: "MyApp.Accounts".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3, - "Expected 3 displayed calls from MyApp.Accounts (1 per caller function)"); - }, - } - - // get_user functions (both arities) call Repo.get - // Per-function deduplication: get_user/1 has 1 call, get_user/2 has 1 call = 2 displayed - crate::execute_test! { - test_name: test_calls_from_function, - fixture: populated_db, - cmd: CallsFromCmd { - module: "MyApp.Accounts".to_string(), - function: Some("get_user".to_string()), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2, - "Expected 2 displayed calls (1 from each get_user arity)"); - // Check that all calls target MyApp.Repo.get - for module in &result.items { - for func in &module.entries { - for call in &func.calls { - assert_eq!(call.callee.module.as_ref(), "MyApp.Repo"); - assert_eq!(call.callee.name.as_ref(), "get"); - } - } - } - }, - } - - // All 11 calls in the fixture are from MyApp.* modules - // Per-function deduplication: each caller keeps unique callees = 11 displayed - crate::execute_test! { - test_name: test_calls_from_regex_module, - fixture: populated_db, - cmd: CallsFromCmd { - module: "MyApp\\..*".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 11, - "Expected 11 displayed calls from MyApp.* modules"); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_test! { - test_name: test_calls_from_no_match, - fixture: populated_db, - cmd: CallsFromCmd { - module: "NonExistent".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(result.items.is_empty(), "Expected no modules for non-existent module"); - assert_eq!(result.total_items, 0); - }, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_calls_from_with_project_filter, - fixture: populated_db, - cmd: CallsFromCmd { - module: "MyApp.Accounts".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // All results should be for the test_project (verified implicitly by getting results) - assert!(result.total_items > 0, "Should have calls with project filter"); - }, - } - - crate::execute_test! { - test_name: test_calls_from_with_limit, - fixture: populated_db, - cmd: CallsFromCmd { - module: "MyApp\\..*".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 1, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 1, "Limit should restrict to 1 call"); - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: CallsFromCmd, - cmd: CallsFromCmd { - module: "MyApp".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/calls_from/mod.rs b/src/commands/calls_from/mod.rs deleted file mode 100644 index f0713b7..0000000 --- a/src/commands/calls_from/mod.rs +++ /dev/null @@ -1,41 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Show what a module/function calls (outgoing edges) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search calls-from MyApp.Accounts # All calls from module - code_search calls-from MyApp.Accounts get_user # Calls from specific function - code_search calls-from MyApp.Accounts get_user 1 # With specific arity")] -pub struct CallsFromCmd { - /// Module name (exact match or pattern with --regex) - pub module: String, - - /// Function name (optional, if not specified shows all calls from module) - pub function: Option, - - /// Function arity (optional, matches all arities if not specified) - pub arity: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for CallsFromCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/calls_from/output.rs b/src/commands/calls_from/output.rs deleted file mode 100644 index d0dac92..0000000 --- a/src/commands/calls_from/output.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Output formatting for calls-from command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::CallerFunction; - -impl TableFormatter for ModuleGroupResult { - type Entry = CallerFunction; - - fn format_header(&self) -> String { - if self.function_pattern.is_none() || self.function_pattern.as_ref().unwrap().is_empty() { - format!("Calls from: {}", self.module_pattern) - } else { - format!("Calls from: {}.{}", self.module_pattern, self.function_pattern.as_ref().unwrap()) - } - } - - fn format_empty_message(&self) -> String { - "No calls found.".to_string() - } - - fn format_summary(&self, total: usize, _module_count: usize) -> String { - format!("Found {} call(s):", total) - } - - fn format_module_header(&self, module_name: &str, module_file: &str) -> String { - format!("{} ({})", module_name, module_file) - } - - fn format_entry(&self, func: &CallerFunction, _module: &str, _file: &str) -> String { - let kind_str = if func.kind.is_empty() { - String::new() - } else { - format!(" [{}]", func.kind) - }; - format!( - "{}/{} ({}:{}){}", - func.name, func.arity, func.start_line, func.end_line, kind_str - ) - } - - fn format_entry_details(&self, func: &CallerFunction, module: &str, file: &str) -> Vec { - func.calls - .iter() - .map(|call| call.format_outgoing(module, file)) - .collect() - } -} diff --git a/src/commands/calls_from/output_tests.rs b/src/commands/calls_from/output_tests.rs deleted file mode 100644 index cd77a74..0000000 --- a/src/commands/calls_from/output_tests.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! Output formatting tests for calls-from command. - -#[cfg(test)] -mod tests { - use super::super::execute::CallerFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Calls from: MyApp.Accounts.get_user - -No calls found."; - - const SINGLE_TABLE: &str = "\ -Calls from: MyApp.Accounts.get_user - -Found 1 call(s): - -MyApp.Accounts (lib/my_app/accounts.ex) - get_user/1 (10:15) - → @ L12 MyApp.Repo.get/2"; - - const MULTIPLE_TABLE: &str = "\ -Calls from: MyApp.Accounts - -Found 2 call(s): - -MyApp.Accounts (lib/my_app/accounts.ex) - get_user/1 (10:15) - → @ L12 MyApp.Repo.get/2 - list_users/0 (20:25) - → @ L22 MyApp.Repo.all/1"; - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - "get_user".to_string(), - vec![], - ) - } - - #[fixture] - fn single_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - "get_user".to_string(), - vec![Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "get_user", - 1, - "", - "lib/my_app/accounts.ex", - 10, - 15, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 12, - call_type: Some("remote".to_string()), - depth: None, - }], - ) - } - - #[fixture] - fn multiple_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Accounts".to_string(), - String::new(), - vec![ - Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "get_user", - 1, - "", - "lib/my_app/accounts.ex", - 10, - 15, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 12, - call_type: Some("remote".to_string()), - depth: None, - }, - Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "list_users", - 0, - "", - "lib/my_app/accounts.ex", - 20, - 25, - ), - callee: FunctionRef::new("MyApp.Repo", "all", 1), - line: 22, - call_type: Some("remote".to_string()), - depth: None, - }, - ], - ) - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: ModuleGroupResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_from", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/calls_to/cli_tests.rs b/src/commands/calls_to/cli_tests.rs deleted file mode 100644 index 0adf137..0000000 --- a/src/commands/calls_to/cli_tests.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! CLI parsing tests for calls-to command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_required_arg_test! { - command: "calls-to", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_option_test! { - command: "calls-to", - variant: CallsTo, - test_name: test_with_module, - args: ["MyApp.Repo"], - field: module, - expected: "MyApp.Repo", - } - - crate::cli_option_test! { - command: "calls-to", - variant: CallsTo, - test_name: test_with_function, - args: ["MyApp.Repo", "get"], - field: function, - expected: Some("get".to_string()), - } - - crate::cli_option_test! { - command: "calls-to", - variant: CallsTo, - test_name: test_with_arity, - args: ["MyApp.Repo", "get", "2"], - field: arity, - expected: Some(2), - } - - crate::cli_option_test! { - command: "calls-to", - variant: CallsTo, - test_name: test_with_regex, - args: ["MyApp\\.Repo", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "calls-to", - variant: CallsTo, - test_name: test_with_limit, - args: ["MyApp.Repo", "--limit", "25"], - field: common.limit, - expected: 25, - } - - crate::cli_limit_tests! { - command: "calls-to", - variant: CallsTo, - required_args: ["MyApp.Repo"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/calls_to/execute.rs b/src/commands/calls_to/execute.rs deleted file mode 100644 index 866d574..0000000 --- a/src/commands/calls_to/execute.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::CallsToCmd; -use crate::commands::Execute; -use crate::queries::calls_to::find_calls_to; -use crate::types::{Call, ModuleGroupResult}; -use crate::utils::group_calls; - -/// A callee function (target) with all its callers -#[derive(Debug, Clone, Serialize)] -pub struct CalleeFunction { - pub name: String, - pub arity: i64, - pub callers: Vec, -} - -impl ModuleGroupResult { - /// Build grouped result from flat calls - pub fn from_calls(module_pattern: String, function_pattern: String, calls: Vec) -> Self { - let (total_items, items) = group_calls( - calls, - // Group by callee module - |call| call.callee.module.to_string(), - // Key by callee function metadata - |call| CalleeFunctionKey { - name: call.callee.name.to_string(), - arity: call.callee.arity, - }, - // Sort by caller module, name, arity, then line - |a, b| { - a.caller.module.as_ref().cmp(b.caller.module.as_ref()) - .then_with(|| a.caller.name.as_ref().cmp(b.caller.name.as_ref())) - .then_with(|| a.caller.arity.cmp(&b.caller.arity)) - .then_with(|| a.line.cmp(&b.line)) - }, - // Deduplicate by caller (module, name, arity) - |c| (c.caller.module.to_string(), c.caller.name.to_string(), c.caller.arity), - // Build CalleeFunction entry - |key, callers| CalleeFunction { - name: key.name, - arity: key.arity, - callers, - }, - // File is intentionally empty because callees are the grouping key, - // and a module can be defined across multiple files. The calls themselves - // carry file information where needed. - |_module, _map| String::new(), - ); - - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } - } -} - -/// Key for grouping by callee function -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct CalleeFunctionKey { - name: String, - arity: i64, -} - -impl Execute for CallsToCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let calls = find_calls_to( - db, - &self.module, - self.function.as_deref(), - self.arity, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(>::from_calls( - self.module, - self.function.unwrap_or_default(), - calls, - )) - } -} diff --git a/src/commands/calls_to/execute_tests.rs b/src/commands/calls_to/execute_tests.rs deleted file mode 100644 index e86d94e..0000000 --- a/src/commands/calls_to/execute_tests.rs +++ /dev/null @@ -1,202 +0,0 @@ -//! Execute tests for calls-to command. - -#[cfg(test)] -mod tests { - use super::super::CallsToCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // 4 calls to MyApp.Repo: get_user/1→get, get_user/2→get, list_users→all, do_fetch→get - crate::execute_test! { - test_name: test_calls_to_module, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 4, - "Expected 4 total calls to MyApp.Repo"); - }, - } - - // 3 calls to Repo.get: from get_user/1, get_user/2, do_fetch - crate::execute_test! { - test_name: test_calls_to_function, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: Some("get".to_string()), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3, - "Expected 3 calls to MyApp.Repo.get"); - }, - } - - crate::execute_test! { - test_name: test_calls_to_function_with_arity, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: Some("get".to_string()), - arity: Some(2), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3); - // All callee functions should be get/2 - for module in &result.items { - for func in &module.entries { - assert_eq!(func.arity, 2); - } - } - }, - } - - // 4 calls match get|all: 3 to get + 1 to all - crate::execute_test! { - test_name: test_calls_to_regex_function, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: Some("get|all".to_string()), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 4, - "Expected 4 calls to get|all"); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_test! { - test_name: test_calls_to_no_match, - fixture: populated_db, - cmd: CallsToCmd { - module: "NonExistent".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(result.items.is_empty(), "Expected no modules for non-existent target"); - assert_eq!(result.total_items, 0); - }, - } - - crate::execute_test! { - test_name: test_calls_to_nonexistent_arity, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: Some("get".to_string()), - arity: Some(99), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(result.items.is_empty(), "Expected no results for non-existent arity"); - assert_eq!(result.total_items, 0); - }, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_calls_to_with_project_filter, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert!(result.total_items > 0, "Should have calls with project filter"); - }, - } - - crate::execute_test! { - test_name: test_calls_to_with_limit, - fixture: populated_db, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 2, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2, "Limit should restrict to 2 calls"); - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: CallsToCmd, - cmd: CallsToCmd { - module: "MyApp.Repo".to_string(), - function: None, - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/calls_to/mod.rs b/src/commands/calls_to/mod.rs deleted file mode 100644 index f4d13d0..0000000 --- a/src/commands/calls_to/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Show what calls a module/function (incoming edges) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search calls-to MyApp.Repo # All callers of module - code_search calls-to MyApp.Repo get # Callers of specific function - code_search calls-to MyApp.Repo get 2 # With specific arity - code_search calls-to MyApp.Accounts get_user # Find all call sites")] -pub struct CallsToCmd { - /// Module name (exact match or pattern with --regex) - pub module: String, - - /// Function name (optional, if not specified shows all calls to module) - pub function: Option, - - /// Function arity (optional, matches all arities if not specified) - pub arity: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for CallsToCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/calls_to/output.rs b/src/commands/calls_to/output.rs deleted file mode 100644 index 2bdbc3d..0000000 --- a/src/commands/calls_to/output.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! Output formatting for calls-to command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::CalleeFunction; - -impl TableFormatter for ModuleGroupResult { - type Entry = CalleeFunction; - - fn format_header(&self) -> String { - if self.function_pattern.is_none() || self.function_pattern.as_ref().unwrap().is_empty() { - format!("Calls to: {}", self.module_pattern) - } else { - format!("Calls to: {}.{}", self.module_pattern, self.function_pattern.as_ref().unwrap()) - } - } - - fn format_empty_message(&self) -> String { - "No callers found.".to_string() - } - - fn format_summary(&self, total: usize, _module_count: usize) -> String { - format!("Found {} caller(s):", total) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - module_name.to_string() - } - - fn format_entry(&self, func: &CalleeFunction, _module: &str, _file: &str) -> String { - format!("{}/{}", func.name, func.arity) - } - - fn format_entry_details(&self, func: &CalleeFunction, module: &str, _file: &str) -> Vec { - // Use empty context file since callers come from different files - func.callers - .iter() - .map(|call| call.format_incoming(module, "")) - .collect() - } -} diff --git a/src/commands/calls_to/output_tests.rs b/src/commands/calls_to/output_tests.rs deleted file mode 100644 index 9e52915..0000000 --- a/src/commands/calls_to/output_tests.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! Output formatting tests for calls-to command. - -#[cfg(test)] -mod tests { - use super::super::execute::CalleeFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Calls to: MyApp.Repo.get - -No callers found."; - - const SINGLE_TABLE: &str = "\ -Calls to: MyApp.Repo.get - -Found 1 caller(s): - -MyApp.Repo - get/2 - ← @ L12 MyApp.Accounts.get_user/1 (accounts.ex:L10:15)"; - - const MULTIPLE_TABLE: &str = "\ -Calls to: MyApp.Repo - -Found 2 caller(s): - -MyApp.Repo - get/2 - ← @ L12 MyApp.Accounts.get_user/1 (accounts.ex:L10:15) - ← @ L40 MyApp.Users.update_user/1 (users.ex:L35:45)"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - "get".to_string(), - vec![], - ) - } - - #[fixture] - fn single_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - "get".to_string(), - vec![Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "get_user", - 1, - "", - "lib/my_app/accounts.ex", - 10, - 15, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 12, - call_type: Some("remote".to_string()), - depth: None, - }], - ) - } - - #[fixture] - fn multiple_result() -> ModuleGroupResult { - >::from_calls( - "MyApp.Repo".to_string(), - String::new(), - vec![ - Call { - caller: FunctionRef::with_definition( - "MyApp.Accounts", - "get_user", - 1, - "", - "lib/my_app/accounts.ex", - 10, - 15, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 12, - call_type: Some("remote".to_string()), - depth: None, - }, - Call { - caller: FunctionRef::with_definition( - "MyApp.Users", - "update_user", - 1, - "", - "lib/my_app/users.ex", - 35, - 45, - ), - callee: FunctionRef::new("MyApp.Repo", "get", 2), - line: 40, - call_type: Some("remote".to_string()), - depth: None, - }, - ], - ) - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: ModuleGroupResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("calls_to", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/clusters/execute.rs b/src/commands/clusters/execute.rs deleted file mode 100644 index 76ddd29..0000000 --- a/src/commands/clusters/execute.rs +++ /dev/null @@ -1,390 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::error::Error; - -use serde::Serialize; - -use super::ClustersCmd; -use crate::commands::Execute; -use crate::queries::clusters::get_module_calls; - -/// A single namespace cluster -#[derive(Debug, Clone, Serialize)] -pub struct ClusterInfo { - pub namespace: String, - pub module_count: usize, - pub internal_calls: i64, - pub outgoing_calls: i64, - pub incoming_calls: i64, - /// Cohesion: internal / (internal + outgoing + incoming) - /// Range 0-1, higher = more self-contained - pub cohesion: f64, - /// Instability: outgoing / (incoming + outgoing) - /// Range 0-1, 0 = stable (depended upon), 1 = unstable (depends on others) - pub instability: f64, -} - -/// A cross-namespace dependency edge -#[derive(Debug, Clone, Serialize)] -pub struct CrossDependency { - pub from_namespace: String, - pub to_namespace: String, - pub call_count: i64, -} - -/// Result of clusters analysis -#[derive(Debug, Serialize)] -pub struct ClustersResult { - pub depth: usize, - pub total_clusters: usize, - pub clusters: Vec, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub cross_dependencies: Vec, -} - -impl Execute for ClustersCmd { - type Output = ClustersResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - // Get all inter-module calls - let calls = get_module_calls(db, &self.common.project)?; - - // Extract namespace for each module and collect all unique modules - let mut all_modules = HashSet::new(); - for call in &calls { - all_modules.insert(call.caller_module.clone()); - all_modules.insert(call.callee_module.clone()); - } - - // Apply module filter if specified (simple substring matching for now) - // Complex regex filtering happens at query level in other commands - let filtered_modules: HashSet = if let Some(ref pattern) = self.module { - all_modules - .into_iter() - .filter(|m| m.contains(pattern)) - .collect() - } else { - all_modules - }; - - // Build namespace -> modules mapping - let mut namespace_modules: HashMap> = HashMap::new(); - for module in &filtered_modules { - let namespace = extract_namespace(module, self.depth); - namespace_modules - .entry(namespace) - .or_insert_with(HashSet::new) - .insert(module.clone()); - } - - // Count internal, outgoing, and incoming calls per namespace - let mut internal_calls: HashMap = HashMap::new(); - let mut outgoing_calls: HashMap = HashMap::new(); - let mut incoming_calls: HashMap = HashMap::new(); - let mut cross_deps: HashMap<(String, String), i64> = HashMap::new(); - - for call in calls { - let caller_ns = extract_namespace(&call.caller_module, self.depth); - let callee_ns = extract_namespace(&call.callee_module, self.depth); - - let caller_in_filter = filtered_modules.contains(&call.caller_module); - let callee_in_filter = filtered_modules.contains(&call.callee_module); - - // Skip calls where neither module is in our filtered set - if !caller_in_filter && !callee_in_filter { - continue; - } - - if caller_ns == callee_ns && caller_in_filter && callee_in_filter { - // Internal call (same namespace, both in filter) - *internal_calls.entry(caller_ns).or_insert(0) += 1; - } else if caller_ns != callee_ns { - // Cross-namespace call - // Count as outgoing for caller namespace (if in filter) - if caller_in_filter { - *outgoing_calls.entry(caller_ns.clone()).or_insert(0) += 1; - } - // Count as incoming for callee namespace (if in filter) - if callee_in_filter { - *incoming_calls.entry(callee_ns.clone()).or_insert(0) += 1; - } - - // Track cross-dependencies (from caller's perspective) - if caller_in_filter { - let key = (caller_ns, callee_ns); - *cross_deps.entry(key).or_insert(0) += 1; - } - } else if caller_in_filter && !callee_in_filter { - // Same namespace but callee outside filter - count as outgoing - *outgoing_calls.entry(caller_ns.clone()).or_insert(0) += 1; - } - } - - // Build cluster info - let mut clusters = Vec::new(); - for (namespace, modules) in namespace_modules { - let internal = internal_calls.get(&namespace).copied().unwrap_or(0); - let outgoing = outgoing_calls.get(&namespace).copied().unwrap_or(0); - let incoming = incoming_calls.get(&namespace).copied().unwrap_or(0); - - // Cohesion: internal / (internal + outgoing + incoming) - let total_interactions = internal + outgoing + incoming; - let cohesion = if total_interactions > 0 { - internal as f64 / total_interactions as f64 - } else { - 0.0 - }; - - // Instability: outgoing / (incoming + outgoing) - // 0 = stable (depended upon), 1 = unstable (depends on others) - let external_total = incoming + outgoing; - let instability = if external_total > 0 { - outgoing as f64 / external_total as f64 - } else { - 0.0 - }; - - clusters.push(ClusterInfo { - namespace, - module_count: modules.len(), - internal_calls: internal, - outgoing_calls: outgoing, - incoming_calls: incoming, - cohesion, - instability, - }); - } - - // Sort by cohesion descending, then by internal calls - clusters.sort_by(|a, b| { - b.cohesion - .partial_cmp(&a.cohesion) - .unwrap_or(std::cmp::Ordering::Equal) - .then_with(|| b.internal_calls.cmp(&a.internal_calls)) - }); - - // Build cross-dependencies if requested - let cross_dependencies = if self.show_dependencies { - let mut deps = Vec::new(); - for ((from_ns, to_ns), count) in cross_deps { - if from_ns != to_ns { - deps.push(CrossDependency { - from_namespace: from_ns, - to_namespace: to_ns, - call_count: count, - }); - } - } - // Sort by call_count descending - deps.sort_by(|a, b| b.call_count.cmp(&a.call_count)); - deps - } else { - Vec::new() - }; - - let total_clusters = clusters.len(); - - Ok(ClustersResult { - depth: self.depth, - total_clusters, - clusters, - cross_dependencies, - }) - } -} - -/// Extract namespace from a module name at the specified depth -/// -/// Example: "MyApp.Accounts.Users.Admin" at depth 2 becomes "MyApp.Accounts" -fn extract_namespace(module: &str, depth: usize) -> String { - module - .split('.') - .take(depth) - .collect::>() - .join(".") -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_extract_namespace_depth_2() { - assert_eq!(extract_namespace("MyApp.Accounts.Users", 2), "MyApp.Accounts"); - } - - #[test] - fn test_extract_namespace_depth_1() { - assert_eq!(extract_namespace("MyApp.Accounts.Users", 1), "MyApp"); - } - - #[test] - fn test_extract_namespace_depth_3() { - assert_eq!(extract_namespace("MyApp.Accounts.Users", 3), "MyApp.Accounts.Users"); - } - - #[test] - fn test_extract_namespace_single_level() { - assert_eq!(extract_namespace("MyApp", 2), "MyApp"); - } - - #[test] - fn test_cohesion_calculation_all_internal() { - // If all calls are internal, cohesion should be 1.0 - let internal = 10; - let outgoing = 0; - let incoming = 0; - let total = internal + outgoing + incoming; - let cohesion = if total > 0 { - internal as f64 / total as f64 - } else { - 0.0 - }; - assert_eq!(cohesion, 1.0); - } - - #[test] - fn test_cohesion_calculation_all_external() { - // If all calls are external (outgoing + incoming), cohesion should be 0.0 - let internal = 0; - let outgoing = 5; - let incoming = 5; - let total = internal + outgoing + incoming; - let cohesion = if total > 0 { - internal as f64 / total as f64 - } else { - 0.0 - }; - assert_eq!(cohesion, 0.0); - } - - #[test] - fn test_cohesion_calculation_mixed() { - // Mixed: internal=45, outgoing=8, incoming=4 → 45/(45+8+4) = 45/57 ≈ 0.79 - let internal = 45; - let outgoing = 8; - let incoming = 4; - let total = internal + outgoing + incoming; - let cohesion = if total > 0 { - internal as f64 / total as f64 - } else { - 0.0 - }; - assert!((cohesion - 0.79).abs() < 0.01); - } - - #[test] - fn test_instability_calculation() { - // Instability = outgoing / (incoming + outgoing) - // outgoing=8, incoming=4 → 8/12 ≈ 0.67 (unstable, depends on others) - let outgoing = 8; - let incoming = 4; - let external_total = incoming + outgoing; - let instability = if external_total > 0 { - outgoing as f64 / external_total as f64 - } else { - 0.0 - }; - assert!((instability - 0.67).abs() < 0.01); - } - - #[test] - fn test_instability_stable_namespace() { - // A namespace with only incoming calls is stable (instability = 0) - let outgoing = 0; - let incoming = 10; - let external_total = incoming + outgoing; - let instability = if external_total > 0 { - outgoing as f64 / external_total as f64 - } else { - 0.0 - }; - assert_eq!(instability, 0.0); - } - - #[test] - fn test_instability_unstable_namespace() { - // A namespace with only outgoing calls is unstable (instability = 1) - let outgoing = 10; - let incoming = 0; - let external_total = incoming + outgoing; - let instability = if external_total > 0 { - outgoing as f64 / external_total as f64 - } else { - 0.0 - }; - assert_eq!(instability, 1.0); - } - - #[test] - fn test_clusters_cmd_structure() { - // Test that ClustersCmd is created correctly with defaults - let cmd = ClustersCmd { - depth: 2, - show_dependencies: false, - module: None, - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 100, - }, - }; - - assert_eq!(cmd.depth, 2); - assert!(!cmd.show_dependencies); - assert_eq!(cmd.module, None); - assert_eq!(cmd.common.project, "default"); - } - - #[test] - fn test_clusters_cmd_with_options() { - let cmd = ClustersCmd { - depth: 3, - show_dependencies: true, - module: Some("MyApp.Core".to_string()), - common: crate::commands::CommonArgs { - project: "custom".to_string(), - regex: false, - limit: 50, - }, - }; - - assert_eq!(cmd.depth, 3); - assert!(cmd.show_dependencies); - assert_eq!(cmd.module, Some("MyApp.Core".to_string())); - assert_eq!(cmd.common.project, "custom"); - } - - #[test] - fn test_cross_dependency_structure() { - let dep = CrossDependency { - from_namespace: "MyApp.Accounts".to_string(), - to_namespace: "MyApp.Repo".to_string(), - call_count: 23, - }; - - assert_eq!(dep.from_namespace, "MyApp.Accounts"); - assert_eq!(dep.to_namespace, "MyApp.Repo"); - assert_eq!(dep.call_count, 23); - } - - #[test] - fn test_cluster_info_structure() { - let cluster = ClusterInfo { - namespace: "MyApp.Accounts".to_string(), - module_count: 5, - internal_calls: 45, - outgoing_calls: 8, - incoming_calls: 4, - cohesion: 0.79, - instability: 0.67, - }; - - assert_eq!(cluster.namespace, "MyApp.Accounts"); - assert_eq!(cluster.module_count, 5); - assert_eq!(cluster.internal_calls, 45); - assert_eq!(cluster.outgoing_calls, 8); - assert_eq!(cluster.incoming_calls, 4); - assert!((cluster.cohesion - 0.79).abs() < 0.001); - assert!((cluster.instability - 0.67).abs() < 0.001); - } -} diff --git a/src/commands/clusters/mod.rs b/src/commands/clusters/mod.rs deleted file mode 100644 index 0c4e1e9..0000000 --- a/src/commands/clusters/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Analyze module connectivity using namespace-based clustering -/// -/// Groups modules by namespace hierarchy and measures internal vs external connectivity. -/// Shows cohesion metrics (internal / (internal + external)) for each cluster. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search clusters # Show all namespace clusters - code_search clusters MyApp.Core # Filter to MyApp.Core namespace - code_search clusters --depth 2 # Cluster at depth 2 (e.g., MyApp.Accounts) - code_search clusters --depth 3 # Cluster at depth 3 (e.g., MyApp.Accounts.Auth) - code_search clusters --show-dependencies # Include cross-namespace call counts -")] -pub struct ClustersCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Namespace depth for clustering (default: 2) - #[arg(long, default_value = "2")] - pub depth: usize, - - /// Show cross-namespace dependencies - #[arg(long)] - pub show_dependencies: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for ClustersCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/clusters/output.rs b/src/commands/clusters/output.rs deleted file mode 100644 index e7e30f8..0000000 --- a/src/commands/clusters/output.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Output formatting for clusters command results. - -use super::execute::ClustersResult; -use crate::output::Outputable; - -impl Outputable for ClustersResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - // Header with depth - lines.push(format!("Module Clusters (depth: {})", self.depth)); - lines.push(String::new()); - - if self.clusters.is_empty() { - lines.push("No clusters found.".to_string()); - return lines.join("\n"); - } - - // Summary - lines.push(format!("Found {} cluster(s):", self.total_clusters)); - lines.push(String::new()); - - // Calculate dynamic column width for namespace - let min_width = 7; // "Cluster".len() - let max_namespace_len = self - .clusters - .iter() - .map(|c| c.namespace.len()) - .max() - .unwrap_or(min_width); - let namespace_width = max_namespace_len.max(min_width); - - // Table header - // Columns: Cluster(dynamic) Modules(7) Internal(8) Out(5) In(5) Cohesion(8) Instab(6) - let header = format!( - "{:7} {:>8} {:>5} {:>5} {:>8} {:>6}", - "Cluster", - "Modules", - "Internal", - "Out", - "In", - "Cohesion", - "Instab", - width = namespace_width - ); - lines.push(header); - lines.push("-".repeat(namespace_width + 45)); - - // Table rows - for cluster in &self.clusters { - let row = format!( - "{:7} {:>8} {:>5} {:>5} {:>8.2} {:>6.2}", - cluster.namespace, - cluster.module_count, - cluster.internal_calls, - cluster.outgoing_calls, - cluster.incoming_calls, - cluster.cohesion, - cluster.instability, - width = namespace_width - ); - lines.push(row); - } - - // Cross-dependencies section - if !self.cross_dependencies.is_empty() { - lines.push(String::new()); - lines.push("Cross-Namespace Dependencies:".to_string()); - lines.push(String::new()); - - for dep in &self.cross_dependencies { - lines.push(format!( - " {} → {}: {} calls", - dep.from_namespace, dep.to_namespace, dep.call_count - )); - } - } - - lines.join("\n") - } -} diff --git a/src/commands/complexity/cli_tests.rs b/src/commands/complexity/cli_tests.rs deleted file mode 100644 index 30385a0..0000000 --- a/src/commands/complexity/cli_tests.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! CLI parsing tests for complexity command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_defaults_test! { - command: "complexity", - variant: Complexity, - required_args: [], - defaults: { - min: 1, - min_depth: 0, - exclude_generated: false, - module: None, - common.project: "default".to_string(), - common.regex: false, - common.limit: 100, - }, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_min, - args: ["--min", "10"], - field: min, - expected: 10, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_min_depth, - args: ["--min-depth", "3"], - field: min_depth, - expected: 3, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_exclude_generated, - args: ["--exclude-generated"], - field: exclude_generated, - expected: true, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_module, - args: ["MyApp.Accounts"], - field: module, - expected: Some("MyApp.Accounts".to_string()), - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_project, - args: ["--project", "my_project"], - field: common.project, - expected: "my_project".to_string(), - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_regex, - args: ["MyApp\\..*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_limit, - args: ["--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_with_limit_short, - args: ["-l", "20"], - field: common.limit, - expected: 20, - } - - crate::cli_limit_tests! { - command: "complexity", - variant: Complexity, - required_args: [], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - crate::cli_option_test! { - command: "complexity", - variant: Complexity, - test_name: test_combined_options, - args: ["MyApp", "--min", "15", "--min-depth", "2", "--exclude-generated", "-l", "30"], - field: min, - expected: 15, - } -} diff --git a/src/commands/complexity/execute.rs b/src/commands/complexity/execute.rs deleted file mode 100644 index 105742b..0000000 --- a/src/commands/complexity/execute.rs +++ /dev/null @@ -1,85 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::ComplexityCmd; -use crate::commands::Execute; -use crate::queries::complexity::find_complexity_metrics; -use crate::types::ModuleCollectionResult; - -/// A single complexity metric entry -#[derive(Debug, Clone, Serialize)] -pub struct ComplexityEntry { - pub name: String, - pub arity: i64, - pub line: i64, - pub complexity: i64, - pub max_nesting_depth: i64, - pub lines: i64, -} - -impl Execute for ComplexityCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let metrics = find_complexity_metrics( - db, - self.min, - self.min_depth, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.exclude_generated, - self.common.limit, - )?; - - let total_items = metrics.len(); - - // Group by module - let items = crate::utils::group_by_module(metrics, |metric| { - let entry = ComplexityEntry { - name: metric.name, - arity: metric.arity, - line: metric.line, - complexity: metric.complexity, - max_nesting_depth: metric.max_nesting_depth, - lines: metric.lines, - }; - (metric.module, entry) - }); - - Ok(ModuleCollectionResult { - module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items, - items, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_complexity_cmd_structure() { - let cmd = ComplexityCmd { - min: 10, - min_depth: 3, - exclude_generated: false, - module: Some("MyApp".to_string()), - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 20, - }, - }; - - assert_eq!(cmd.min, 10); - assert_eq!(cmd.min_depth, 3); - assert!(!cmd.exclude_generated); - assert_eq!(cmd.module, Some("MyApp".to_string())); - } -} diff --git a/src/commands/complexity/execute_tests.rs b/src/commands/complexity/execute_tests.rs deleted file mode 100644 index 5f189fd..0000000 --- a/src/commands/complexity/execute_tests.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! Execute tests for complexity command. - -#[cfg(test)] -mod tests { - use super::super::ComplexityCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // Test with default thresholds (min >= 1, depth >= 0) - crate::execute_test! { - test_name: test_complexity_default_thresholds, - fixture: populated_db, - cmd: ComplexityCmd { - min: 1, - min_depth: 0, - exclude_generated: false, - module: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // With default thresholds, all functions should be included (default complexity is 1) - assert_eq!(result.total_items, 15); - assert_eq!(result.items.len(), 5); // 5 modules - }, - } - - // Test with higher complexity threshold filters out lower complexity functions - crate::execute_test! { - test_name: test_complexity_high_threshold, - fixture: populated_db, - cmd: ComplexityCmd { - min: 10, - min_depth: 0, - exclude_generated: false, - module: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // No functions should exceed complexity 10 with default fixture - assert_eq!(result.total_items, 0); - assert!(result.items.is_empty()); - }, - } - - // Test with min depth filter - crate::execute_test! { - test_name: test_complexity_min_depth, - fixture: populated_db, - cmd: ComplexityCmd { - min: 1, - min_depth: 5, - exclude_generated: false, - module: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // No functions should have depth >= 5 with default fixture - assert_eq!(result.total_items, 0); - }, - } - - // Test with module filter - crate::execute_test! { - test_name: test_complexity_with_module_filter, - fixture: populated_db, - cmd: ComplexityCmd { - min: 1, - min_depth: 0, - exclude_generated: false, - module: Some("MyApp.Accounts".to_string()), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // Should only return MyApp.Accounts module (4 functions) - assert_eq!(result.total_items, 4); - assert_eq!(result.items.len(), 1); - assert_eq!(result.items[0].name, "MyApp.Accounts"); - assert_eq!(result.items[0].entries.len(), 4); - }, - } - - // Test with module regex filter - crate::execute_test! { - test_name: test_complexity_with_module_regex, - fixture: populated_db, - cmd: ComplexityCmd { - min: 1, - min_depth: 0, - exclude_generated: false, - module: Some("MyApp\\..*".to_string()), - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - // Should return all MyApp.* modules - assert_eq!(result.total_items, 15); - assert_eq!(result.items.len(), 5); - }, - } - - // Test limit parameter - crate::execute_test! { - test_name: test_complexity_with_limit, - fixture: populated_db, - cmd: ComplexityCmd { - min: 1, - min_depth: 0, - exclude_generated: false, - module: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 5, - }, - }, - assertions: |result| { - // With limit of 5, should get at most 5 functions - assert_eq!(result.total_items, 5); - }, - } - - // ========================================================================= - // Empty database tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: ComplexityCmd, - cmd: ComplexityCmd { - min: 1, - min_depth: 0, - exclude_generated: false, - module: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/complexity/mod.rs b/src/commands/complexity/mod.rs deleted file mode 100644 index d8e7d23..0000000 --- a/src/commands/complexity/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -mod execute; -mod output; - -#[cfg(test)] -mod cli_tests; -#[cfg(test)] -mod execute_tests; -#[cfg(test)] -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Display complexity metrics for functions -/// -/// Shows functions with complexity scores and nesting depths. -/// Complexity is a measure of the cyclomatic complexity of a function, -/// and nesting depth is the maximum depth of nested control structures. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search complexity # Show all functions with complexity >= 1 - code_search complexity MyApp.Accounts # Filter to MyApp.Accounts module - code_search complexity --min 10 # Show functions with complexity >= 10 - code_search complexity --min-depth 3 # Show functions with nesting depth >= 3 - code_search complexity --exclude-generated # Exclude macro-generated functions - code_search complexity -l 20 # Show top 20 most complex functions -")] -pub struct ComplexityCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Minimum complexity threshold - #[arg(long, default_value = "1")] - pub min: i64, - - /// Minimum nesting depth threshold - #[arg(long, default_value = "0")] - pub min_depth: i64, - - /// Exclude macro-generated functions - #[arg(long)] - pub exclude_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for ComplexityCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/complexity/output.rs b/src/commands/complexity/output.rs deleted file mode 100644 index 0acc4dc..0000000 --- a/src/commands/complexity/output.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Output formatting for complexity command results. - -use super::execute::ComplexityEntry; -use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; - -impl TableFormatter for ModuleCollectionResult { - type Entry = ComplexityEntry; - - fn format_header(&self) -> String { - "Complexity".to_string() - } - - fn format_empty_message(&self) -> String { - "No functions found with the specified complexity thresholds.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} function(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, entry: &ComplexityEntry, _module: &str, _file: &str) -> String { - format!( - "{}/{} complexity: {}, depth: {}, lines: {}", - entry.name, entry.arity, entry.complexity, entry.max_nesting_depth, entry.lines - ) - } - - fn blank_before_module(&self) -> bool { - true - } - - fn blank_after_summary(&self) -> bool { - false - } -} diff --git a/src/commands/complexity/output_tests.rs b/src/commands/complexity/output_tests.rs deleted file mode 100644 index 47b6d01..0000000 --- a/src/commands/complexity/output_tests.rs +++ /dev/null @@ -1,123 +0,0 @@ -//! Output formatting tests for complexity command. - -#[cfg(test)] -mod tests { - use super::super::execute::ComplexityEntry; - use crate::output::Outputable; - use crate::types::{ModuleCollectionResult, ModuleGroup}; - - #[test] - fn test_format_table_single_function() { - let result = ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: "lib/my_app/accounts.ex".to_string(), - entries: vec![ComplexityEntry { - name: "create_user".to_string(), - arity: 1, - line: 10, - complexity: 12, - max_nesting_depth: 4, - lines: 45, - }], - function_count: None, - }], - }; - - let output = result.format(crate::output::OutputFormat::Table); - assert!(output.contains("Complexity")); - assert!(output.contains("MyApp.Accounts")); - assert!(output.contains("create_user/1")); - assert!(output.contains("complexity: 12")); - assert!(output.contains("depth: 4")); - assert!(output.contains("lines: 45")); - } - - #[test] - fn test_format_table_empty() { - let result: ModuleCollectionResult = ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 0, - items: vec![], - }; - - let output = result.format(crate::output::OutputFormat::Table); - assert!(output.contains("Complexity")); - assert!(output.contains("No functions found")); - } - - #[test] - fn test_format_json() { - let result = ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: "lib/my_app/accounts.ex".to_string(), - entries: vec![ComplexityEntry { - name: "create_user".to_string(), - arity: 1, - line: 10, - complexity: 12, - max_nesting_depth: 4, - lines: 45, - }], - function_count: None, - }], - }; - - let output = result.format(crate::output::OutputFormat::Json); - // Verify it's valid JSON - let parsed: serde_json::Value = - serde_json::from_str(&output).expect("Output should be valid JSON"); - assert_eq!( - parsed["total_items"], 1, - "total_items should be 1" - ); - assert_eq!( - parsed["items"][0]["entries"][0]["complexity"], 12, - "complexity should be 12" - ); - } - - #[test] - fn test_format_toon() { - let result = ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Service".to_string(), - file: "lib/my_app/service.ex".to_string(), - entries: vec![ComplexityEntry { - name: "process".to_string(), - arity: 1, - line: 5, - complexity: 8, - max_nesting_depth: 3, - lines: 25, - }], - function_count: None, - }], - }; - - let output = result.format(crate::output::OutputFormat::Toon); - // Verify it contains expected toon output elements - assert!(output.contains("MyApp.Service")); - assert!(output.contains("process")); - assert!(output.contains("8")); // complexity - } -} diff --git a/src/commands/cycles/execute.rs b/src/commands/cycles/execute.rs deleted file mode 100644 index 9eb497c..0000000 --- a/src/commands/cycles/execute.rs +++ /dev/null @@ -1,274 +0,0 @@ -//! Cycle detection execution and DFS-based cycle reconstruction. - -use std::collections::{HashMap, HashSet}; -use std::error::Error; - -use serde::Serialize; - -use super::CyclesCmd; -use crate::commands::Execute; -use crate::queries::cycles::find_cycle_edges; - -/// A single cycle found in the module dependency graph -#[derive(Debug, Clone, Serialize)] -pub struct Cycle { - /// Length of the cycle (number of modules) - pub length: usize, - /// Ordered path of modules: A → B → C → A - pub modules: Vec, -} - -/// Result of cycle detection -#[derive(Debug, Serialize)] -pub struct CyclesResult { - /// Total number of distinct cycles found - pub total_cycles: usize, - /// Total number of unique modules involved in cycles - pub modules_in_cycles: usize, - /// The detected cycles - pub cycles: Vec, -} - -impl Execute for CyclesCmd { - type Output = CyclesResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - // Get cycle edges from the database - let edges = find_cycle_edges( - db, - &self.common.project, - self.module.as_deref(), - )?; - - if edges.is_empty() { - return Ok(CyclesResult { - total_cycles: 0, - modules_in_cycles: 0, - cycles: vec![], - }); - } - - // Build adjacency list from edges - let mut graph: HashMap> = HashMap::new(); - let mut all_modules = HashSet::new(); - - for edge in &edges { - graph - .entry(edge.from.clone()) - .or_insert_with(Vec::new) - .push(edge.to.clone()); - all_modules.insert(edge.from.clone()); - all_modules.insert(edge.to.clone()); - } - - // Find cycles using DFS from each node - let mut cycles = find_all_cycles(&graph, &all_modules); - - // Filter by max_length if provided - if let Some(max_len) = self.max_length { - cycles.retain(|c| c.length <= max_len); - } - - // Filter by involving module if provided - if let Some(involving) = &self.involving { - cycles.retain(|c| c.modules.iter().any(|m| m.contains(involving))); - } - - // Deduplicate cycles (same modules in different starting positions are the same cycle) - cycles = deduplicate_cycles(cycles); - - // Count unique modules in cycles - let modules_in_cycles: HashSet<_> = cycles - .iter() - .flat_map(|c| c.modules.iter().cloned()) - .collect(); - - Ok(CyclesResult { - total_cycles: cycles.len(), - modules_in_cycles: modules_in_cycles.len(), - cycles, - }) - } -} - -/// Find all cycles starting from each node in the graph using DFS -fn find_all_cycles(graph: &HashMap>, all_modules: &HashSet) -> Vec { - let mut cycles = Vec::new(); - - for start_node in all_modules { - let found = dfs_find_cycles(graph, start_node, start_node, vec![], &mut HashSet::new()); - cycles.extend(found); - } - - cycles -} - -/// DFS to find cycles starting from a given node -fn dfs_find_cycles( - graph: &HashMap>, - current: &str, - start: &str, - path: Vec, - visited: &mut HashSet, -) -> Vec { - let mut cycles = Vec::new(); - let mut new_path = path.clone(); - new_path.push(current.to_string()); - - // If we've revisited the start node and have more than one edge in the path, - // we've found a cycle - if current == start && !path.is_empty() { - // Only report if we haven't already found this cycle - // (cycles of length > 1 where start != first path node) - if path.len() > 0 { - cycles.push(Cycle { - length: new_path.len() - 1, // Don't count the repeated start node - modules: path.clone(), - }); - } - return cycles; - } - - // Prevent infinite recursion on the same node in the current path - if new_path.len() > 1 && path.contains(¤t.to_string()) { - return cycles; - } - - // Explore neighbors - if let Some(neighbors) = graph.get(current) { - for neighbor in neighbors { - let found = dfs_find_cycles(graph, neighbor, start, new_path.clone(), visited); - cycles.extend(found); - } - } - - cycles -} - -/// Remove duplicate cycles (same modules in different orders/rotations) -fn deduplicate_cycles(cycles: Vec) -> Vec { - let mut unique = Vec::new(); - let mut seen = HashSet::new(); - - for cycle in cycles { - // Normalize the cycle representation: sort to get canonical form - let mut sorted = cycle.modules.clone(); - sorted.sort(); - let canonical = format!("{:?}", sorted); - - if !seen.contains(&canonical) { - seen.insert(canonical); - unique.push(cycle); - } - } - - // Sort cycles by length and first module for consistent output - unique.sort_by(|a, b| { - a.length.cmp(&b.length).then_with(|| { - a.modules - .first() - .cmp(&b.modules.first()) - }) - }); - - unique -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_find_cycles_simple_two_module_cycle() { - let mut graph = HashMap::new(); - graph.insert("A".to_string(), vec!["B".to_string()]); - graph.insert("B".to_string(), vec!["A".to_string()]); - - let mut modules = HashSet::new(); - modules.insert("A".to_string()); - modules.insert("B".to_string()); - - let cycles = find_all_cycles(&graph, &modules); - let unique = deduplicate_cycles(cycles); - - // A-B-A should be detected as one cycle - assert_eq!(unique.len(), 1); - assert_eq!(unique[0].length, 2); - assert!(unique[0].modules.contains(&"A".to_string())); - assert!(unique[0].modules.contains(&"B".to_string())); - } - - #[test] - fn test_find_cycles_three_module_cycle() { - let mut graph = HashMap::new(); - graph.insert("A".to_string(), vec!["B".to_string()]); - graph.insert("B".to_string(), vec!["C".to_string()]); - graph.insert("C".to_string(), vec!["A".to_string()]); - - let mut modules = HashSet::new(); - modules.insert("A".to_string()); - modules.insert("B".to_string()); - modules.insert("C".to_string()); - - let cycles = find_all_cycles(&graph, &modules); - let unique = deduplicate_cycles(cycles); - - assert_eq!(unique.len(), 1); - assert_eq!(unique[0].length, 3); - } - - #[test] - fn test_find_cycles_no_cycles() { - let mut graph = HashMap::new(); - graph.insert("A".to_string(), vec!["B".to_string()]); - graph.insert("B".to_string(), vec!["C".to_string()]); - - let mut modules = HashSet::new(); - modules.insert("A".to_string()); - modules.insert("B".to_string()); - modules.insert("C".to_string()); - - let cycles = find_all_cycles(&graph, &modules); - assert_eq!(cycles.len(), 0); - } - - #[test] - fn test_deduplicate_cycles() { - let cycles = vec![ - Cycle { - length: 2, - modules: vec!["A".to_string(), "B".to_string()], - }, - Cycle { - length: 2, - modules: vec!["B".to_string(), "A".to_string()], - }, - ]; - - let unique = deduplicate_cycles(cycles); - assert_eq!(unique.len(), 1); - } - - #[test] - fn test_max_length_filter() { - let mut graph = HashMap::new(); - graph.insert("A".to_string(), vec!["B".to_string()]); - graph.insert("B".to_string(), vec!["C".to_string()]); - graph.insert("C".to_string(), vec!["A".to_string()]); - - let mut modules = HashSet::new(); - modules.insert("A".to_string()); - modules.insert("B".to_string()); - modules.insert("C".to_string()); - - let cycles = find_all_cycles(&graph, &modules); - let unique = deduplicate_cycles(cycles); - - assert_eq!(unique.len(), 1); - assert_eq!(unique[0].length, 3); - - // Filter to max_length 2 - let filtered: Vec<_> = unique.iter().filter(|c| c.length <= 2).cloned().collect(); - assert_eq!(filtered.len(), 0); - } -} diff --git a/src/commands/cycles/mod.rs b/src/commands/cycles/mod.rs deleted file mode 100644 index c1b96c7..0000000 --- a/src/commands/cycles/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Detect circular dependencies between modules -/// -/// Analyzes the call graph to find cycles where modules directly or indirectly -/// depend on each other, creating circular imports or call loops. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search cycles # Find all cycles - code_search cycles MyApp.Core # Filter to MyApp.Core namespace - code_search cycles --max-length 3 # Only show cycles of length <= 3 - code_search cycles --involving MyApp.Accounts # Only cycles involving Accounts -")] -pub struct CyclesCmd { - /// Module filter pattern (substring or regex with -r) - pub module: Option, - - /// Maximum cycle length to find - #[arg(long)] - pub max_length: Option, - - /// Only show cycles involving this module (substring match) - #[arg(long)] - pub involving: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for CyclesCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/cycles/output.rs b/src/commands/cycles/output.rs deleted file mode 100644 index 0393853..0000000 --- a/src/commands/cycles/output.rs +++ /dev/null @@ -1,125 +0,0 @@ -//! Output formatting for cycles command results. - -use super::execute::CyclesResult; -use crate::output::Outputable; - -impl Outputable for CyclesResult { - fn to_table(&self) -> String { - if self.cycles.is_empty() { - return "No circular dependencies found.\n".to_string(); - } - - let mut output = String::new(); - output.push_str("Circular Dependencies\n\n"); - output.push_str(&format!("Found {} cycle(s):\n\n", self.total_cycles)); - - for (idx, cycle) in self.cycles.iter().enumerate() { - output.push_str(&format!("Cycle {} (length {}):\n", idx + 1, cycle.length)); - - // Format the cycle path with arrows - for (i, module) in cycle.modules.iter().enumerate() { - if i == 0 { - output.push_str(" "); - } else { - output.push_str("\n → "); - } - output.push_str(module); - } - - // Show closing arrow back to first module - if !cycle.modules.is_empty() { - output.push_str("\n → "); - output.push_str(&cycle.modules[0]); - } - - output.push_str("\n\n"); - } - - output.push_str(&format!( - "Total: {} module(s) involved in cycles\n", - self.modules_in_cycles - )); - - output - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::commands::cycles::execute::Cycle; - - #[test] - fn test_cycles_output_format_empty() { - let result = CyclesResult { - total_cycles: 0, - modules_in_cycles: 0, - cycles: vec![], - }; - - let output = result.to_table(); - assert!(output.contains("No circular dependencies found")); - } - - #[test] - fn test_cycles_output_format_single_cycle() { - let result = CyclesResult { - total_cycles: 1, - modules_in_cycles: 2, - cycles: vec![Cycle { - length: 2, - modules: vec!["MyApp.Accounts".to_string(), "MyApp.Auth".to_string()], - }], - }; - - let output = result.to_table(); - assert!(output.contains("Cycle 1 (length 2)")); - assert!(output.contains("MyApp.Accounts")); - assert!(output.contains("MyApp.Auth")); - assert!(output.contains("Total: 2 module(s) involved in cycles")); - } - - #[test] - fn test_cycles_output_format_multiple_cycles() { - let result = CyclesResult { - total_cycles: 2, - modules_in_cycles: 5, - cycles: vec![ - Cycle { - length: 2, - modules: vec!["A".to_string(), "B".to_string()], - }, - Cycle { - length: 3, - modules: vec![ - "C".to_string(), - "D".to_string(), - "E".to_string(), - ], - }, - ], - }; - - let output = result.to_table(); - assert!(output.contains("Cycle 1 (length 2)")); - assert!(output.contains("Cycle 2 (length 3)")); - assert!(output.contains("Total: 5 module(s) involved in cycles")); - } - - #[test] - fn test_cycles_output_json() { - let result = CyclesResult { - total_cycles: 1, - modules_in_cycles: 2, - cycles: vec![Cycle { - length: 2, - modules: vec!["A".to_string(), "B".to_string()], - }], - }; - - let json = serde_json::to_string(&result).unwrap(); - assert!(json.contains("total_cycles")); - assert!(json.contains("modules_in_cycles")); - assert!(json.contains("cycles")); - } -} diff --git a/src/commands/depended_by/cli_tests.rs b/src/commands/depended_by/cli_tests.rs deleted file mode 100644 index 40fab0f..0000000 --- a/src/commands/depended_by/cli_tests.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! CLI parsing tests for depended-by command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_required_arg_test! { - command: "depended-by", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_option_test! { - command: "depended-by", - variant: DependedBy, - test_name: test_with_module, - args: ["MyApp.Repo"], - field: module, - expected: "MyApp.Repo", - } - - crate::cli_option_test! { - command: "depended-by", - variant: DependedBy, - test_name: test_with_regex, - args: ["MyApp\\..*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "depended-by", - variant: DependedBy, - test_name: test_with_limit, - args: ["MyApp.Repo", "--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_limit_tests! { - command: "depended-by", - variant: DependedBy, - required_args: ["MyApp.Repo"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/depended_by/execute.rs b/src/commands/depended_by/execute.rs deleted file mode 100644 index ccb45ab..0000000 --- a/src/commands/depended_by/execute.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; - -use serde::Serialize; - -use super::DependedByCmd; -use crate::commands::Execute; -use crate::queries::depended_by::find_dependents; -use crate::types::{Call, ModuleGroupResult, ModuleGroup}; - -/// A target function being called in the dependency module -#[derive(Debug, Clone, Serialize)] -pub struct DependentTarget { - pub function: String, - pub arity: i64, - pub line: i64, -} - -/// A caller function in a dependent module -#[derive(Debug, Clone, Serialize)] -pub struct DependentCaller { - pub function: String, - pub arity: i64, - pub kind: String, - pub start_line: i64, - pub end_line: i64, - pub file: String, - pub targets: Vec, -} - -impl ModuleGroupResult { - /// Build a grouped structure from flat calls - pub fn from_calls(target_module: String, calls: Vec) -> Self { - let total_items = calls.len(); - - if calls.is_empty() { - return ModuleGroupResult { - module_pattern: target_module, - function_pattern: None, - total_items: 0, - items: vec![], - }; - } - - // Group by caller_module -> caller_function -> targets - // Using BTreeMap for automatic sorting by module and function key - let mut by_module: BTreeMap>> = BTreeMap::new(); - for call in &calls { - by_module - .entry(call.caller.module.to_string()) - .or_default() - .entry((call.caller.name.to_string(), call.caller.arity)) - .or_default() - .push(call); - } - - let items: Vec> = by_module - .into_iter() - .map(|(module_name, callers_map)| { - // Determine module file from first caller in first function - let module_file = callers_map - .values() - .next() - .and_then(|calls| calls.first()) - .and_then(|call| call.caller.file.as_deref()) - .unwrap_or("") - .to_string(); - - let entries: Vec = callers_map - .into_iter() - .map(|((func_name, arity), func_calls)| { - let first = func_calls[0]; - - let targets: Vec = func_calls - .iter() - .map(|c| DependentTarget { - function: c.callee.name.to_string(), - arity: c.callee.arity, - line: c.line, - }) - .collect(); - - DependentCaller { - function: func_name, - arity, - kind: first.caller.kind.as_deref().unwrap_or("").to_string(), - start_line: first.caller.start_line.unwrap_or(0), - end_line: first.caller.end_line.unwrap_or(0), - file: first.caller.file.as_deref().unwrap_or("").to_string(), - targets, - } - }) - .collect(); - - ModuleGroup { - name: module_name, - file: module_file, - entries, - function_count: None, - } - }) - .collect(); - - ModuleGroupResult { - module_pattern: target_module, - function_pattern: None, - total_items, - items, - } - } -} - -impl Execute for DependedByCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let calls = find_dependents( - db, - &self.module, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(>::from_calls(self.module, calls)) - } -} diff --git a/src/commands/depended_by/execute_tests.rs b/src/commands/depended_by/execute_tests.rs deleted file mode 100644 index 6f6a0ee..0000000 --- a/src/commands/depended_by/execute_tests.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Execute tests for depended-by command. - -#[cfg(test)] -mod tests { - use super::super::DependedByCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // MyApp.Repo is depended on by: Accounts (3 calls), Service (1 call via do_fetch) - crate::execute_test! { - test_name: test_depended_by_single_module, - fixture: populated_db, - cmd: DependedByCmd { - module: "MyApp.Repo".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.items.len(), 2); - assert!(result.items.iter().any(|m| m.name == "MyApp.Accounts")); - assert!(result.items.iter().any(|m| m.name == "MyApp.Service")); - }, - } - - crate::execute_test! { - test_name: test_depended_by_counts_calls, - fixture: populated_db, - cmd: DependedByCmd { - module: "MyApp.Repo".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // Accounts has 3 callers, Service has 1 - let accounts = result.items.iter().find(|m| m.name == "MyApp.Accounts").unwrap(); - let service = result.items.iter().find(|m| m.name == "MyApp.Service").unwrap(); - let accounts_calls: usize = accounts.entries.iter().map(|c| c.targets.len()).sum(); - let service_calls: usize = service.entries.iter().map(|c| c.targets.len()).sum(); - assert_eq!(accounts_calls, 3); - assert_eq!(service_calls, 1); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_depended_by_no_match, - fixture: populated_db, - cmd: DependedByCmd { - module: "NonExistent".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: items, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_all_match_test! { - test_name: test_depended_by_excludes_self, - fixture: populated_db, - cmd: DependedByCmd { - module: "MyApp.Repo".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - collection: items, - condition: |m| m.name != "MyApp.Repo", - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: DependedByCmd, - cmd: DependedByCmd { - module: "MyApp".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/depended_by/mod.rs b/src/commands/depended_by/mod.rs deleted file mode 100644 index d52f684..0000000 --- a/src/commands/depended_by/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Show what modules depend on a given module (incoming module dependencies) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search depended-by MyApp.Repo # Who depends on Repo? - code_search depended-by 'Ecto\\..*' -r # Who depends on Ecto modules?")] -pub struct DependedByCmd { - /// Module name (exact match or pattern with --regex) - pub module: String, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for DependedByCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/depended_by/output.rs b/src/commands/depended_by/output.rs deleted file mode 100644 index abb7081..0000000 --- a/src/commands/depended_by/output.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Output formatting for depended-by command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::DependentCaller; - -impl TableFormatter for ModuleGroupResult { - type Entry = DependentCaller; - - fn format_header(&self) -> String { - format!("Modules that depend on: {}", self.module_pattern) - } - - fn format_empty_message(&self) -> String { - "No dependents found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} call(s) from {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, caller: &DependentCaller, _module: &str, _file: &str) -> String { - let kind_str = if caller.kind.is_empty() { - String::new() - } else { - format!(" [{}]", caller.kind) - }; - // Extract just the filename from path - let filename = caller.file.rsplit('/').next().unwrap_or(&caller.file); - format!( - "{}/{}{} ({}:L{}:{}):", - caller.function, caller.arity, kind_str, - filename, caller.start_line, caller.end_line - ) - } - - fn format_entry_details(&self, caller: &DependentCaller, _module: &str, _file: &str) -> Vec { - caller - .targets - .iter() - .map(|target| format!("→ @ L{} {}/{}", target.line, target.function, target.arity)) - .collect() - } -} diff --git a/src/commands/depended_by/output_tests.rs b/src/commands/depended_by/output_tests.rs deleted file mode 100644 index d1a27d7..0000000 --- a/src/commands/depended_by/output_tests.rs +++ /dev/null @@ -1,176 +0,0 @@ -//! Output formatting tests for depended-by command. - -#[cfg(test)] -mod tests { - use super::super::execute::{DependentCaller, DependentTarget}; - use crate::types::{ModuleGroupResult, ModuleGroup}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Modules that depend on: MyApp.Repo - -No dependents found."; - - const SINGLE_TABLE: &str = "\ -Modules that depend on: MyApp.Repo - -Found 1 call(s) from 1 module(s): - -MyApp.Service: - fetch/1 [def] (service.ex:L10:20): - → @ L15 get/2"; - - const MULTIPLE_TABLE: &str = "\ -Modules that depend on: MyApp.Repo - -Found 2 call(s) from 2 module(s): - -MyApp.Controller: - show/1 [def] (controller.ex:L15:25): - → @ L20 get/2 -MyApp.Service: - fetch/1 [def] (service.ex:L10:20): - → @ L15 get/2"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Repo".to_string(), - function_pattern: None, - total_items: 0, - items: vec![], - } - } - - #[fixture] - fn single_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Repo".to_string(), - function_pattern: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Service".to_string(), - file: String::new(), - entries: vec![DependentCaller { - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "lib/service.ex".to_string(), - targets: vec![DependentTarget { - function: "get".to_string(), - arity: 2, - line: 15, - }], - }], - function_count: None, - }], - } - } - - #[fixture] - fn multiple_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Repo".to_string(), - function_pattern: None, - total_items: 2, - items: vec![ - ModuleGroup { - name: "MyApp.Controller".to_string(), - file: String::new(), - entries: vec![DependentCaller { - function: "show".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 15, - end_line: 25, - file: "lib/controller.ex".to_string(), - targets: vec![DependentTarget { - function: "get".to_string(), - arity: 2, - line: 20, - }], - }], - function_count: None, - }, - ModuleGroup { - name: "MyApp.Service".to_string(), - file: String::new(), - entries: vec![DependentCaller { - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "lib/service.ex".to_string(), - targets: vec![DependentTarget { - function: "get".to_string(), - arity: 2, - line: 15, - }], - }], - function_count: None, - }, - ], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: ModuleGroupResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depended_by", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/depends_on/cli_tests.rs b/src/commands/depends_on/cli_tests.rs deleted file mode 100644 index 18a8d2b..0000000 --- a/src/commands/depends_on/cli_tests.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! CLI parsing tests for depends-on command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_required_arg_test! { - command: "depends-on", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_option_test! { - command: "depends-on", - variant: DependsOn, - test_name: test_with_module, - args: ["MyApp.Accounts"], - field: module, - expected: "MyApp.Accounts", - } - - crate::cli_option_test! { - command: "depends-on", - variant: DependsOn, - test_name: test_with_regex, - args: ["MyApp\\..*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "depends-on", - variant: DependsOn, - test_name: test_with_limit, - args: ["MyApp.Accounts", "--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_limit_tests! { - command: "depends-on", - variant: DependsOn, - required_args: ["MyApp.Accounts"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/depends_on/execute.rs b/src/commands/depends_on/execute.rs deleted file mode 100644 index a645581..0000000 --- a/src/commands/depends_on/execute.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; - -use serde::Serialize; - -use super::DependsOnCmd; -use crate::commands::Execute; -use crate::queries::depends_on::find_dependencies; -use crate::types::{Call, ModuleGroupResult}; -use crate::utils::convert_to_module_groups; - -/// A function in a dependency module being called -#[derive(Debug, Clone, Serialize)] -pub struct DependencyFunction { - pub name: String, - pub arity: i64, - pub callers: Vec, -} - -impl ModuleGroupResult { - /// Build a grouped structure from flat calls - pub fn from_calls(source_module: String, calls: Vec) -> Self { - let total_items = calls.len(); - - if calls.is_empty() { - return ModuleGroupResult { - module_pattern: source_module, - function_pattern: None, - total_items: 0, - items: vec![], - }; - } - - // Group by callee_module -> callee_function -> callers - // Using BTreeMap for automatic sorting - let mut by_module: BTreeMap>> = BTreeMap::new(); - for call in calls { - by_module - .entry(call.callee.module.to_string()) - .or_default() - .entry((call.callee.name.to_string(), call.callee.arity)) - .or_default() - .push(call); - } - - // Convert to ModuleGroup structure - let items = convert_to_module_groups( - by_module, - |(func_name, arity), callers| DependencyFunction { - name: func_name, - arity, - callers, - }, - // File is intentionally empty because dependencies are the grouping key, - // and a module can depend on functions defined across multiple files. - // The dependency targets themselves carry file information where needed. - |_module, _map| String::new(), - ); - - ModuleGroupResult { - module_pattern: source_module, - function_pattern: None, - total_items, - items, - } - } -} - -impl Execute for DependsOnCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let calls = find_dependencies( - db, - &self.module, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(>::from_calls(self.module, calls)) - } -} diff --git a/src/commands/depends_on/execute_tests.rs b/src/commands/depends_on/execute_tests.rs deleted file mode 100644 index dc23276..0000000 --- a/src/commands/depends_on/execute_tests.rs +++ /dev/null @@ -1,110 +0,0 @@ -//! Execute tests for depends-on command. - -#[cfg(test)] -mod tests { - use super::super::DependsOnCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // Controller depends on: Accounts (2 calls: list_users, get_user) and Service (1 call: process) - crate::execute_test! { - test_name: test_depends_on_single_module, - fixture: populated_db, - cmd: DependsOnCmd { - module: "MyApp.Controller".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.items.len(), 2); - assert!(result.items.iter().any(|m| m.name == "MyApp.Accounts")); - assert!(result.items.iter().any(|m| m.name == "MyApp.Service")); - }, - } - - // Service depends on: Repo (1 call via do_fetch) and Notifier (1 call via process) - // Self-calls (process→fetch, fetch→do_fetch) are excluded - crate::execute_test! { - test_name: test_depends_on_counts_calls, - fixture: populated_db, - cmd: DependsOnCmd { - module: "MyApp.Service".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.items.len(), 2); - assert!(result.items.iter().any(|m| m.name == "MyApp.Repo")); - assert!(result.items.iter().any(|m| m.name == "MyApp.Notifier")); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_depends_on_no_match, - fixture: populated_db, - cmd: DependsOnCmd { - module: "NonExistent".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: items, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_all_match_test! { - test_name: test_depends_on_excludes_self, - fixture: populated_db, - cmd: DependsOnCmd { - module: "MyApp.Repo".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - collection: items, - condition: |m| m.name != "MyApp.Repo", - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: DependsOnCmd, - cmd: DependsOnCmd { - module: "MyApp".to_string(), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/depends_on/mod.rs b/src/commands/depends_on/mod.rs deleted file mode 100644 index ea72d6b..0000000 --- a/src/commands/depends_on/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Show what modules a given module depends on (outgoing module dependencies) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search depends-on MyApp.Accounts # What does Accounts depend on? - code_search depends-on 'MyApp\\.Web.*' -r # Dependencies of Web modules")] -pub struct DependsOnCmd { - /// Module name (exact match or pattern with --regex) - pub module: String, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for DependsOnCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/depends_on/output.rs b/src/commands/depends_on/output.rs deleted file mode 100644 index 784e713..0000000 --- a/src/commands/depends_on/output.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! Output formatting for depends-on command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::DependencyFunction; - -impl TableFormatter for ModuleGroupResult { - type Entry = DependencyFunction; - - fn format_header(&self) -> String { - format!("Dependencies of: {}", self.module_pattern) - } - - fn format_empty_message(&self) -> String { - "No dependencies found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} call(s) to {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, func: &DependencyFunction, _module: &str, _file: &str) -> String { - format!("{}/{}:", func.name, func.arity) - } - - fn format_entry_details(&self, func: &DependencyFunction, module: &str, _file: &str) -> Vec { - // Use empty context since callers come from different files - func.callers - .iter() - .map(|call| call.format_incoming(module, "")) - .collect() - } -} diff --git a/src/commands/depends_on/output_tests.rs b/src/commands/depends_on/output_tests.rs deleted file mode 100644 index 7c74549..0000000 --- a/src/commands/depends_on/output_tests.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! Output formatting tests for depends-on command. - -#[cfg(test)] -mod tests { - use super::super::execute::DependencyFunction; - use crate::types::{Call, FunctionRef, ModuleGroupResult, ModuleGroup}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Dependencies of: MyApp.Controller - -No dependencies found."; - - const SINGLE_TABLE: &str = "\ -Dependencies of: MyApp.Controller - -Found 1 call(s) to 1 module(s): - -MyApp.Service: - process/1: - ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12)"; - - const MULTIPLE_TABLE: &str = "\ -Dependencies of: MyApp.Controller - -Found 2 call(s) to 2 module(s): - -MyApp.Service: - process/1: - ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12) -Phoenix.View: - render/2: - ← @ L20 MyApp.Controller.show/1 [def] (controller.ex:L15:25)"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Controller".to_string(), - function_pattern: None, - total_items: 0, - items: vec![], - } - } - - #[fixture] - fn single_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Controller".to_string(), - function_pattern: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Service".to_string(), - file: String::new(), - entries: vec![DependencyFunction { - name: "process".to_string(), - arity: 1, - callers: vec![Call { - caller: FunctionRef::with_definition( - "MyApp.Controller", - "index", - 1, - "def", - "lib/controller.ex", - 5, - 12, - ), - callee: FunctionRef::new("MyApp.Service", "process", 1), - line: 7, - call_type: None, - depth: None, - }], - }], - function_count: None, - }], - } - } - - #[fixture] - fn multiple_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Controller".to_string(), - function_pattern: None, - total_items: 2, - items: vec![ - ModuleGroup { - name: "MyApp.Service".to_string(), - file: String::new(), - entries: vec![DependencyFunction { - name: "process".to_string(), - arity: 1, - callers: vec![Call { - caller: FunctionRef::with_definition( - "MyApp.Controller", - "index", - 1, - "def", - "lib/controller.ex", - 5, - 12, - ), - callee: FunctionRef::new("MyApp.Service", "process", 1), - line: 7, - call_type: None, - depth: None, - }], - }], - function_count: None, - }, - ModuleGroup { - name: "Phoenix.View".to_string(), - file: String::new(), - entries: vec![DependencyFunction { - name: "render".to_string(), - arity: 2, - callers: vec![Call { - caller: FunctionRef::with_definition( - "MyApp.Controller", - "show", - 1, - "def", - "lib/controller.ex", - 15, - 25, - ), - callee: FunctionRef::new("Phoenix.View", "render", 2), - line: 20, - call_type: None, - depth: None, - }], - }], - function_count: None, - }, - ], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: ModuleGroupResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("depends_on", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/describe/descriptions.rs b/src/commands/describe/descriptions.rs deleted file mode 100644 index e90f5cf..0000000 --- a/src/commands/describe/descriptions.rs +++ /dev/null @@ -1,488 +0,0 @@ -//! Centralized descriptions for all available commands. - -use serde::{Serialize, Deserialize}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum CommandCategory { - Query, - Analysis, - Search, - Type, - Module, - Other, -} - -impl std::fmt::Display for CommandCategory { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Query => write!(f, "Query Commands"), - Self::Analysis => write!(f, "Analysis Commands"), - Self::Search => write!(f, "Search Commands"), - Self::Type => write!(f, "Type Search Commands"), - Self::Module => write!(f, "Module Commands"), - Self::Other => write!(f, "Other Commands"), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Example { - pub description: String, - pub command: String, -} - -impl Example { - pub fn new(description: &str, command: &str) -> Self { - Self { - description: description.to_string(), - command: command.to_string(), - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct CommandDescription { - pub name: String, - pub brief: String, - pub category: CommandCategory, - pub description: String, - pub usage: String, - pub examples: Vec, - pub related: Vec, -} - -impl CommandDescription { - pub fn new( - name: &str, - brief: &str, - category: CommandCategory, - description: &str, - usage: &str, - ) -> Self { - Self { - name: name.to_string(), - brief: brief.to_string(), - category, - description: description.to_string(), - usage: usage.to_string(), - examples: Vec::new(), - related: Vec::new(), - } - } - - pub fn with_examples(mut self, examples: Vec) -> Self { - self.examples = examples; - self - } - - pub fn with_related(mut self, related: Vec<&str>) -> Self { - self.related = related.iter().map(|s| s.to_string()).collect(); - self - } -} - -/// Get all available command descriptions -pub fn all_descriptions() -> Vec { - vec![ - // Query Commands - CommandDescription::new( - "calls-to", - "Find callers of a given function", - CommandCategory::Query, - "Finds all functions that call a specific function. Use this to answer: 'Who calls this function?'", - "code_search calls-to [FUNCTION] [ARITY] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all callers of MyApp.Repo.get/2", "code_search calls-to MyApp.Repo get 2"), - Example::new("Find callers of any function in a module", "code_search calls-to MyApp.Repo"), - ]) - .with_related(vec!["calls-from", "trace", "path"]), - - CommandDescription::new( - "calls-from", - "Find what a function calls", - CommandCategory::Query, - "Finds all functions that are called by a specific function. Use this to answer: 'What does this function call?'", - "code_search calls-from [FUNCTION] [ARITY] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all functions called by MyApp.Repo.get/2", "code_search calls-from MyApp.Repo get 2"), - Example::new("Find what a module calls", "code_search calls-from MyApp.Accounts"), - ]) - .with_related(vec!["calls-to", "trace", "path"]), - - CommandDescription::new( - "trace", - "Forward call trace from a function", - CommandCategory::Query, - "Traces call chains forward from a starting function. Shows the full path of calls that can be reached from a given function.", - "code_search trace [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Trace all calls from a function", "code_search trace MyApp.API create_user"), - Example::new("Limit trace depth to 3 levels", "code_search trace MyApp.API create_user --depth 3"), - ]) - .with_related(vec!["calls-from", "reverse-trace", "path"]), - - CommandDescription::new( - "reverse-trace", - "Backward call trace to a function", - CommandCategory::Query, - "Traces call chains backward to a target function. Shows all code paths that can lead to a given function.", - "code_search reverse-trace [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all paths leading to a function", "code_search reverse-trace MyApp.API validate_token"), - Example::new("Limit trace depth to 2 levels", "code_search reverse-trace MyApp.API validate_token --depth 2"), - ]) - .with_related(vec!["calls-to", "trace", "path"]), - - CommandDescription::new( - "path", - "Find a call path between two functions", - CommandCategory::Query, - "Finds one or more call paths connecting two functions. Useful for understanding how code flows from a source to a target.", - "code_search path --from-module --from-function --to-module --to-function ", - ) - .with_examples(vec![ - Example::new("Find call path between two functions", "code_search path --from-module MyApp.API --from-function create_user --to-module MyApp.DB --to-function insert"), - ]) - .with_related(vec!["trace", "reverse-trace", "calls-from"]), - - // Analysis Commands - CommandDescription::new( - "hotspots", - "Find high-connectivity functions", - CommandCategory::Analysis, - "Identifies functions with the most incoming or outgoing calls. \ - Use -k incoming (default) for most-called functions, -k outgoing for functions that call many others, \ - -k total for highest combined connectivity, or -k ratio for boundary functions.", - "code_search hotspots [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Most called functions", "code_search hotspots"), - Example::new("Functions calling many others", "code_search hotspots -k outgoing"), - Example::new("Highest total connections", "code_search hotspots -k total"), - Example::new("Boundary functions (high ratio)", "code_search hotspots -k ratio"), - Example::new("Filter to namespace", "code_search hotspots MyApp -l 20"), - ]) - .with_related(vec!["god-modules", "boundaries", "complexity"]), - - CommandDescription::new( - "unused", - "Find functions that are never called", - CommandCategory::Analysis, - "Identifies functions with no incoming calls. Use -p to find dead code (unused private functions) \ - or -P to find entry points (public functions not called internally). Use -x to exclude \ - compiler-generated functions like __struct__, __info__, etc.", - "code_search unused [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all unused functions", "code_search unused"), - Example::new("Filter to a specific module", "code_search unused MyApp.Utils"), - Example::new("Find dead code (unused private)", "code_search unused -p"), - Example::new("Find entry points (unused public)", "code_search unused -Px"), - ]) - .with_related(vec!["hotspots", "duplicates", "large-functions"]), - - CommandDescription::new( - "god-modules", - "Find god modules - modules with high function count, LoC, and connectivity", - CommandCategory::Analysis, - "Identifies modules that are overly large or have too much responsibility. \ - Use --min-functions, --min-loc, and --min-total to set thresholds for function count, \ - lines of code, and connectivity respectively.", - "code_search god-modules [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all god modules", "code_search god-modules"), - Example::new("Filter to a namespace", "code_search god-modules MyApp.Core"), - Example::new("With minimum 500 LoC", "code_search god-modules --min-loc 500"), - Example::new("With minimum 30 functions", "code_search god-modules --min-functions 30"), - ]) - .with_related(vec!["hotspots", "boundaries", "complexity"]), - - CommandDescription::new( - "boundaries", - "Find boundary modules with high fan-in but low fan-out", - CommandCategory::Analysis, - "Identifies modules that many others depend on but have few dependencies. These are key integration points. \ - Use --min-incoming to set a threshold for incoming calls and --min-ratio for the fan-in/fan-out ratio.", - "code_search boundaries [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all boundary modules", "code_search boundaries"), - Example::new("Filter to a namespace", "code_search boundaries MyApp.Web"), - Example::new("Set minimum incoming calls", "code_search boundaries --min-incoming 5"), - Example::new("Set minimum ratio threshold", "code_search boundaries --min-ratio 3.0"), - ]) - .with_related(vec!["god-modules", "hotspots", "depends-on"]), - - CommandDescription::new( - "duplicates", - "Find functions with identical or near-identical implementations", - CommandCategory::Analysis, - "Identifies duplicate code that could be consolidated into reusable functions. \ - Uses AST matching by default; use --exact for source-level matching. \ - Use --by-module to rank modules by duplication count. \ - Use --exclude-generated to filter out macro-generated functions.", - "code_search duplicates [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all duplicate functions", "code_search duplicates"), - Example::new("Find duplicates in a module", "code_search duplicates MyApp.Utils"), - Example::new("Use exact source matching", "code_search duplicates --exact"), - Example::new("Rank modules by duplication", "code_search duplicates --by-module"), - Example::new("Exclude generated functions", "code_search duplicates --exclude-generated"), - ]) - .with_related(vec!["unused", "large-functions", "hotspots"]), - - CommandDescription::new( - "complexity", - "Display complexity metrics for functions", - CommandCategory::Analysis, - "Shows cyclomatic complexity and nesting depth for functions. \ - Use --min and --min-depth to filter by thresholds. Generated functions are excluded by default.", - "code_search complexity [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Show all functions with complexity >= 1", "code_search complexity"), - Example::new("Filter to a namespace", "code_search complexity MyApp.Accounts"), - Example::new("Find highly complex functions", "code_search complexity --min 10"), - Example::new("Find deeply nested functions", "code_search complexity --min-depth 3"), - ]) - .with_related(vec!["large-functions", "many-clauses", "hotspots"]), - - CommandDescription::new( - "large-functions", - "Find large functions that may need refactoring", - CommandCategory::Analysis, - "Identifies functions that are large by line count (50+ lines by default), sorted by size descending. \ - Use --min-lines to adjust the threshold. Generated functions are excluded by default.", - "code_search large-functions [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all large functions", "code_search large-functions"), - Example::new("Filter to a namespace", "code_search large-functions MyApp.Web"), - Example::new("Find functions with 100+ lines", "code_search large-functions --min-lines 100"), - Example::new("Include generated functions", "code_search large-functions --include-generated"), - ]) - .with_related(vec!["complexity", "many-clauses", "hotspots"]), - - CommandDescription::new( - "many-clauses", - "Find functions with many pattern-matched heads", - CommandCategory::Analysis, - "Identifies functions with many clauses/definitions (5+ by default), sorted by clause count descending. \ - Use --min-clauses to adjust the threshold. Generated functions are excluded by default.", - "code_search many-clauses [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find functions with many clauses", "code_search many-clauses"), - Example::new("Filter to a namespace", "code_search many-clauses MyApp.Web"), - Example::new("Find functions with 10+ clauses", "code_search many-clauses --min-clauses 10"), - Example::new("Include generated functions", "code_search many-clauses --include-generated"), - ]) - .with_related(vec!["complexity", "large-functions", "hotspots"]), - - CommandDescription::new( - "cycles", - "Detect circular dependencies between modules", - CommandCategory::Analysis, - "Finds circular dependencies in the module dependency graph, which indicate architectural issues. \ - Use --max-length to limit cycle size and --involving to find cycles containing a specific module.", - "code_search cycles [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all circular dependencies", "code_search cycles"), - Example::new("Filter to a namespace", "code_search cycles MyApp.Core"), - Example::new("Find short cycles only", "code_search cycles --max-length 3"), - Example::new("Find cycles involving a module", "code_search cycles --involving MyApp.Accounts"), - ]) - .with_related(vec!["depends-on", "depended-by", "boundaries"]), - - // Search Commands - CommandDescription::new( - "search", - "Search for modules or functions by name pattern", - CommandCategory::Search, - "Finds modules or functions matching a given pattern. Use this as a starting point for other analyses.", - "code_search search [-k modules|functions] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find modules containing 'User'", "code_search search User"), - Example::new("Find functions starting with 'get_'", "code_search search get_ -k functions"), - Example::new("Use regex pattern", "code_search search -r '^MyApp\\.API'"), - ]) - .with_related(vec!["location", "function", "browse-module"]), - - CommandDescription::new( - "location", - "Find where a function is defined", - CommandCategory::Search, - "Shows the file path and line numbers where a function is defined. Useful for quickly navigating to code.", - "code_search location [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find any function named 'validate'", "code_search location validate"), - Example::new("Find location of a function in a module", "code_search location get MyApp.Repo"), - ]) - .with_related(vec!["search", "function", "browse-module"]), - - CommandDescription::new( - "function", - "Show function signature", - CommandCategory::Search, - "Displays the full signature of a function including arguments, return type, and metadata.", - "code_search function [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Show function signature", "code_search function MyApp.Repo get -a 2"), - ]) - .with_related(vec!["search", "location", "accepts"]), - - CommandDescription::new( - "browse-module", - "Browse all definitions in a module or file", - CommandCategory::Module, - "Lists all functions, structs, and other definitions in a module. Great for exploring unfamiliar code.", - "code_search browse-module -m [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Browse a module", "code_search browse-module -m MyApp.Accounts"), - Example::new("Browse with limit", "code_search browse-module -m MyApp.Accounts --limit 50"), - ]) - .with_related(vec!["search", "location", "struct-usage"]), - - // Type Search Commands - CommandDescription::new( - "accepts", - "Find functions accepting a specific type pattern", - CommandCategory::Type, - "Finds all functions that have a parameter matching a type pattern. Useful for finding consumers of a type.", - "code_search accepts [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find functions accepting a type", "code_search accepts User.t"), - Example::new("Use regex for type pattern", "code_search accepts 'list\\(.*\\)' -r"), - ]) - .with_related(vec!["returns", "struct-usage", "function"]), - - CommandDescription::new( - "returns", - "Find functions returning a specific type pattern", - CommandCategory::Type, - "Finds all functions that return a type matching a pattern. Useful for finding providers of a type.", - "code_search returns [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find functions returning a type", "code_search returns ':ok'"), - Example::new("Use regex for type pattern", "code_search returns 'tuple\\(.*\\)' -r"), - ]) - .with_related(vec!["accepts", "struct-usage", "function"]), - - CommandDescription::new( - "struct-usage", - "Find functions that work with a given struct type", - CommandCategory::Type, - "Lists functions that accept or return a specific type pattern. Use --by-module to aggregate counts per module.", - "code_search struct-usage [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find all functions using a struct", "code_search struct-usage User.t"), - Example::new("Summarize by module", "code_search struct-usage User.t --by-module"), - ]) - .with_related(vec!["accepts", "returns", "browse-module"]), - - // Module Commands - CommandDescription::new( - "depends-on", - "Show what modules a given module depends on", - CommandCategory::Module, - "Lists all modules that a given module calls or depends on. Shows outgoing module dependencies.", - "code_search depends-on [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find module dependencies", "code_search depends-on MyApp.API"), - ]) - .with_related(vec!["depended-by", "cycles", "boundaries"]), - - CommandDescription::new( - "depended-by", - "Show what modules depend on a given module", - CommandCategory::Module, - "Lists all modules that call or depend on a given module. Shows incoming module dependencies.", - "code_search depended-by [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Find modules that depend on this one", "code_search depended-by MyApp.Repo"), - ]) - .with_related(vec!["depends-on", "cycles", "boundaries"]), - - CommandDescription::new( - "clusters", - "Analyze module connectivity using namespace-based clustering", - CommandCategory::Module, - "Groups modules into clusters based on their namespace structure and interdependencies.\n\n\ - Output columns:\n\ - - Internal: calls between modules within the same namespace\n\ - - Out: calls from this namespace to other namespaces\n\ - - In: calls from other namespaces into this one\n\ - - Cohesion: internal / (internal + out + in) — higher = more self-contained\n\ - - Instab: out / (in + out) — 0 = stable (depended upon), 1 = unstable (depends on others)", - "code_search clusters [MODULE] [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Show all namespace clusters", "code_search clusters"), - Example::new("Filter to a namespace", "code_search clusters MyApp.Core"), - Example::new("Cluster at depth 3", "code_search clusters --depth 3"), - Example::new("Show cross-namespace dependencies", "code_search clusters --show-dependencies"), - ]) - .with_related(vec!["god-modules", "boundaries", "depends-on"]), - - // Other Commands - CommandDescription::new( - "setup", - "Create database schema without importing data", - CommandCategory::Other, - "Initializes a new database with the required schema for storing call graph data.", - "code_search setup [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Create database schema", "code_search setup --db ./my_project.db"), - Example::new("Force recreate", "code_search setup --db ./my_project.db --force"), - ]) - .with_related(vec!["import"]), - - CommandDescription::new( - "import", - "Import a call graph JSON file into the database", - CommandCategory::Other, - "Loads call graph data from a JSON file into the database. Must run setup first.", - "code_search import --file [OPTIONS]", - ) - .with_examples(vec![ - Example::new("Import call graph data", "code_search import --file call_graph.json"), - ]) - .with_related(vec!["setup"]), - ] -} - -/// Get a single command description by name -pub fn get_description(name: &str) -> Option { - all_descriptions().into_iter().find(|d| d.name == name) -} - -/// Get all descriptions grouped by category -pub fn descriptions_by_category() -> std::collections::BTreeMap> { - let mut map = std::collections::BTreeMap::new(); - - for desc in all_descriptions() { - map.entry(desc.category) - .or_insert_with(Vec::new) - .push((desc.name.clone(), desc.brief.clone())); - } - - map -} diff --git a/src/commands/describe/execute.rs b/src/commands/describe/execute.rs deleted file mode 100644 index 2e2db5a..0000000 --- a/src/commands/describe/execute.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::error::Error; -use serde::Serialize; - -use super::DescribeCmd; -use super::descriptions::{CommandDescription, get_description, descriptions_by_category}; -use crate::commands::Execute; - -/// Output for listing all commands by category -#[derive(Debug, Clone, Serialize)] -pub struct CategoryListing { - pub category: String, - pub commands: Vec<(String, String)>, // (name, brief) -} - -/// Output for describe mode -#[derive(Debug, Serialize)] -#[serde(untagged)] -pub enum DescribeMode { - ListAll { - categories: Vec, - }, - Specific { - descriptions: Vec, - }, -} - -/// Result of the describe command -#[derive(Debug, Serialize)] -pub struct DescribeResult { - #[serde(flatten)] - pub mode: DescribeMode, -} - -impl Execute for DescribeCmd { - type Output = DescribeResult; - - fn execute(self, _db: &cozo::DbInstance) -> Result> { - if self.commands.is_empty() { - // List all commands grouped by category - let categories_map = descriptions_by_category(); - let mut categories = Vec::new(); - - for (category, commands) in categories_map { - categories.push(CategoryListing { - category: category.to_string(), - commands, - }); - } - - Ok(DescribeResult { - mode: DescribeMode::ListAll { categories }, - }) - } else { - // Get descriptions for specified commands - let mut descriptions = Vec::new(); - - for cmd_name in self.commands { - match get_description(&cmd_name) { - Some(desc) => descriptions.push(desc), - None => { - return Err(format!("Unknown command: '{}'", cmd_name).into()); - } - } - } - - Ok(DescribeResult { - mode: DescribeMode::Specific { descriptions }, - }) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_describe_all_lists_categories() { - let cmd = DescribeCmd { - commands: vec![], - }; - - let result = cmd.execute(&Default::default()).expect("Should succeed"); - - match result.mode { - DescribeMode::ListAll { ref categories } => { - assert!(!categories.is_empty()); - // Check we have commands in categories - let total_commands: usize = categories.iter().map(|c| c.commands.len()).sum(); - assert!(total_commands > 0); - } - _ => panic!("Expected ListAll mode"), - } - } - - #[test] - fn test_describe_specific_command() { - let cmd = DescribeCmd { - commands: vec!["calls-to".to_string()], - }; - - let result = cmd.execute(&Default::default()).expect("Should succeed"); - - match result.mode { - DescribeMode::Specific { ref descriptions } => { - assert_eq!(descriptions.len(), 1); - assert_eq!(descriptions[0].name, "calls-to"); - } - _ => panic!("Expected Specific mode"), - } - } - - #[test] - fn test_describe_multiple_commands() { - let cmd = DescribeCmd { - commands: vec![ - "calls-to".to_string(), - "calls-from".to_string(), - "trace".to_string(), - ], - }; - - let result = cmd.execute(&Default::default()).expect("Should succeed"); - - match result.mode { - DescribeMode::Specific { ref descriptions } => { - assert_eq!(descriptions.len(), 3); - let names: Vec<_> = descriptions.iter().map(|d| d.name.as_str()).collect(); - assert!(names.contains(&"calls-to")); - assert!(names.contains(&"calls-from")); - assert!(names.contains(&"trace")); - } - _ => panic!("Expected Specific mode"), - } - } - - #[test] - fn test_describe_unknown_command() { - let cmd = DescribeCmd { - commands: vec!["nonexistent".to_string()], - }; - - let result = cmd.execute(&Default::default()); - assert!(result.is_err()); - } -} diff --git a/src/commands/describe/mod.rs b/src/commands/describe/mod.rs deleted file mode 100644 index f80a258..0000000 --- a/src/commands/describe/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -mod descriptions; -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Display detailed documentation about available commands -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search describe # List all available commands - code_search describe calls-to # Detailed info about calls-to command - code_search describe calls-to calls-from trace # Describe multiple commands")] -pub struct DescribeCmd { - /// Command(s) to describe (if empty, lists all) - pub commands: Vec, -} - -impl CommandRunner for DescribeCmd { - fn run(self, _db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(_db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/describe/output.rs b/src/commands/describe/output.rs deleted file mode 100644 index 7353376..0000000 --- a/src/commands/describe/output.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! Output formatting for describe command results. - -use crate::output::Outputable; -use super::execute::{DescribeResult, DescribeMode, CategoryListing}; -use super::descriptions::CommandDescription; - -impl Outputable for DescribeResult { - fn to_table(&self) -> String { - match &self.mode { - DescribeMode::ListAll { categories } => format_list_all(categories), - DescribeMode::Specific { descriptions } => format_specific(descriptions), - } - } -} - -fn format_list_all(categories: &[CategoryListing]) -> String { - let mut output = String::new(); - output.push_str("Available Commands\n"); - output.push_str("\n"); - - for category in categories { - output.push_str(&format!("{}:\n", category.category)); - for (name, brief) in &category.commands { - output.push_str(&format!(" {:<20} {}\n", name, brief)); - } - output.push_str("\n"); - } - - output.push_str("Use 'code_search describe ' for detailed information.\n"); - output -} - -fn format_specific(descriptions: &[CommandDescription]) -> String { - let mut output = String::new(); - - for (i, desc) in descriptions.iter().enumerate() { - if i > 0 { - output.push_str("\n"); - output.push_str("================================================================================\n"); - output.push_str("\n"); - } - - // Title - output.push_str(&format!("{} - {}\n", desc.name, desc.brief)); - output.push_str("\n"); - - // Description - output.push_str("DESCRIPTION\n"); - output.push_str(&format!(" {}\n", desc.description)); - output.push_str("\n"); - - // Usage - output.push_str("USAGE\n"); - output.push_str(&format!(" {}\n", desc.usage)); - output.push_str("\n"); - - // Examples - if !desc.examples.is_empty() { - output.push_str("EXAMPLES\n"); - for example in &desc.examples { - output.push_str(&format!(" # {}\n", example.description)); - output.push_str(&format!(" {}\n", example.command)); - output.push_str("\n"); - } - } - - // Related commands - if !desc.related.is_empty() { - output.push_str("RELATED COMMANDS\n"); - for related in &desc.related { - output.push_str(&format!(" {}\n", related)); - } - output.push_str("\n"); - } - } - - output -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::commands::describe::descriptions::Example; - - #[test] - fn test_format_list_all() { - let categories = vec![ - CategoryListing { - category: "Query Commands".to_string(), - commands: vec![ - ("calls-to".to_string(), "Find callers of a given function".to_string()), - ("calls-from".to_string(), "Find what a function calls".to_string()), - ], - }, - CategoryListing { - category: "Analysis Commands".to_string(), - commands: vec![ - ("hotspots".to_string(), "Find high-connectivity functions".to_string()), - ], - }, - ]; - - let output = format_list_all(&categories); - assert!(output.contains("Available Commands")); - assert!(output.contains("Query Commands")); - assert!(output.contains("Analysis Commands")); - assert!(output.contains("calls-to")); - assert!(output.contains("hotspots")); - assert!(output.contains("Use 'code_search describe ' for detailed information.")); - } - - #[test] - fn test_format_specific_single() { - let descriptions = vec![ - CommandDescription::new( - "calls-to", - "Find callers of a given function", - crate::commands::describe::descriptions::CommandCategory::Query, - "Finds all functions that call a specific function.", - "code_search calls-to -m -f ", - ) - .with_examples(vec![ - Example::new("Find all callers", "code_search calls-to -m MyApp.Repo -f get"), - ]) - .with_related(vec!["calls-from", "trace"]), - ]; - - let output = format_specific(&descriptions); - assert!(output.contains("calls-to - Find callers of a given function")); - assert!(output.contains("DESCRIPTION")); - assert!(output.contains("USAGE")); - assert!(output.contains("EXAMPLES")); - assert!(output.contains("Find all callers")); - assert!(output.contains("RELATED COMMANDS")); - assert!(output.contains("calls-from")); - } - - #[test] - fn test_format_specific_multiple() { - let descriptions = vec![ - CommandDescription::new( - "calls-to", - "Find callers", - crate::commands::describe::descriptions::CommandCategory::Query, - "Finds all callers.", - "code_search calls-to", - ), - CommandDescription::new( - "calls-from", - "Find callees", - crate::commands::describe::descriptions::CommandCategory::Query, - "Finds what is called.", - "code_search calls-from", - ), - ]; - - let output = format_specific(&descriptions); - assert!(output.contains("calls-to")); - assert!(output.contains("calls-from")); - assert!(output.contains("================================================================================")); - } -} diff --git a/src/commands/duplicates/cli_tests.rs b/src/commands/duplicates/cli_tests.rs deleted file mode 100644 index 1feeea5..0000000 --- a/src/commands/duplicates/cli_tests.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! CLI parsing tests for duplicates command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // Duplicates has no required args - crate::cli_defaults_test! { - command: "duplicates", - variant: Duplicates, - required_args: [], - defaults: { - common.project: "default", - common.regex: false, - exact: false, - by_module: false, - exclude_generated: false, - common.limit: 100, - }, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_module, - args: ["MyApp"], - field: module, - expected: Some("MyApp".to_string()), - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_exact, - args: ["--exact"], - field: exact, - expected: true, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_by_module, - args: ["--by-module"], - field: by_module, - expected: true, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_exclude_generated, - args: ["--exclude-generated"], - field: exclude_generated, - expected: true, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_regex, - args: ["MyApp.*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_limit, - args: ["--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_limit_short, - args: ["-l", "75"], - field: common.limit, - expected: 75, - } - - crate::cli_option_test! { - command: "duplicates", - variant: Duplicates, - test_name: test_with_project, - args: ["--project", "my_project"], - field: common.project, - expected: "my_project", - } - - crate::cli_error_test! { - command: "duplicates", - test_name: test_limit_zero_rejected, - args: ["--limit", "0"], - } - - crate::cli_error_test! { - command: "duplicates", - test_name: test_limit_exceeds_max_rejected, - args: ["--limit", "1001"], - } -} diff --git a/src/commands/duplicates/execute.rs b/src/commands/duplicates/execute.rs deleted file mode 100644 index 8428e2a..0000000 --- a/src/commands/duplicates/execute.rs +++ /dev/null @@ -1,191 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; - -use serde::Serialize; - -use super::DuplicatesCmd; -use crate::commands::Execute; -use crate::queries::duplicates::find_duplicates; - -// ============================================================================= -// Detailed mode types (default) -// ============================================================================= - -/// Result structure for duplicates command - grouped by hash -#[derive(Debug, Clone, Serialize)] -pub struct DuplicatesResult { - pub total_groups: usize, - pub total_duplicates: usize, - pub groups: Vec, -} - -/// A group of functions with the same hash -#[derive(Debug, Clone, Serialize)] -pub struct DuplicateGroup { - pub hash: String, - pub functions: Vec, -} - -/// A function within a duplicate group -#[derive(Debug, Clone, Serialize)] -pub struct DuplicateFunctionEntry { - pub module: String, - pub name: String, - pub arity: i64, - pub line: i64, - pub file: String, -} - -// ============================================================================= -// ByModule mode types -// ============================================================================= - -/// Result structure for --by-module mode - ranked by module -#[derive(Debug, Clone, Serialize)] -pub struct DuplicatesByModuleResult { - pub total_modules: usize, - pub total_duplicates: i64, - pub modules: Vec, -} - -/// A module with its duplicate functions -#[derive(Debug, Clone, Serialize)] -pub struct ModuleDuplicates { - pub name: String, - pub duplicate_count: i64, - pub top_duplicates: Vec, -} - -/// Summary of a duplicated function -#[derive(Debug, Clone, Serialize)] -pub struct DuplicateSummary { - pub name: String, - pub arity: i64, - pub copy_count: i64, -} - -// ============================================================================= -// Output enum -// ============================================================================= - -/// Output type that can be either detailed or aggregated by module -#[derive(Debug, Serialize)] -#[serde(untagged)] -pub enum DuplicatesOutput { - Detailed(DuplicatesResult), - ByModule(DuplicatesByModuleResult), -} - -// ============================================================================= -// Execute implementation -// ============================================================================= - -impl Execute for DuplicatesCmd { - type Output = DuplicatesOutput; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let functions = find_duplicates( - db, - &self.common.project, - self.module.as_deref(), - self.common.regex, - self.exact, - self.exclude_generated, - )?; - - if self.by_module { - Ok(DuplicatesOutput::ByModule(build_by_module_result(functions))) - } else { - Ok(DuplicatesOutput::Detailed(build_detailed_result(functions))) - } - } -} - -fn build_detailed_result( - functions: Vec, -) -> DuplicatesResult { - // Group by hash - let mut groups_map: BTreeMap> = BTreeMap::new(); - - for func in functions { - let entry = DuplicateFunctionEntry { - module: func.module, - name: func.name, - arity: func.arity, - line: func.line, - file: func.file, - }; - groups_map.entry(func.hash).or_default().push(entry); - } - - // Convert to result format - let total_duplicates = groups_map.values().map(|v| v.len()).sum(); - let groups = groups_map - .into_iter() - .map(|(hash, functions)| DuplicateGroup { hash, functions }) - .collect::>(); - let total_groups = groups.len(); - - DuplicatesResult { - total_groups, - total_duplicates, - groups, - } -} - -fn build_by_module_result( - functions: Vec, -) -> DuplicatesByModuleResult { - // Group by module first - let mut module_map: BTreeMap> = BTreeMap::new(); - - for func in functions { - module_map - .entry(func.module) - .or_default() - .push((func.hash, func.name, func.arity)); - } - - // Aggregate by module and find top duplicates per module - let mut modules = Vec::new(); - for (module_name, funcs) in module_map { - // Group by function name/arity to count copies - let mut func_map: BTreeMap<(String, i64), i64> = BTreeMap::new(); - - for (_hash, name, arity) in &funcs { - let key = (name.clone(), *arity); - *func_map.entry(key).or_insert(0) += 1; - } - - // Convert to DuplicateSummary and sort by copy count (descending) - let mut summaries: Vec = func_map - .into_iter() - .map(|((name, arity), count)| DuplicateSummary { - name, - arity, - copy_count: count, - }) - .collect(); - - summaries.sort_by(|a, b| b.copy_count.cmp(&a.copy_count)); - - let duplicate_count = summaries.len() as i64; - modules.push(ModuleDuplicates { - name: module_name, - duplicate_count, - top_duplicates: summaries, - }); - } - - // Sort modules by duplicate count (descending) - modules.sort_by(|a, b| b.duplicate_count.cmp(&a.duplicate_count)); - - let total_duplicates: i64 = modules.iter().map(|m| m.duplicate_count).sum(); - let total_modules = modules.len(); - - DuplicatesByModuleResult { - total_modules, - total_duplicates, - modules, - } -} diff --git a/src/commands/duplicates/execute_tests.rs b/src/commands/duplicates/execute_tests.rs deleted file mode 100644 index 0cf47db..0000000 --- a/src/commands/duplicates/execute_tests.rs +++ /dev/null @@ -1,230 +0,0 @@ -//! Execute tests for duplicates command. - -#[cfg(test)] -mod tests { - use super::super::DuplicatesCmd; - use crate::commands::duplicates::execute::DuplicatesOutput; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests (detailed mode - default) - // ========================================================================= - - crate::execute_test! { - test_name: test_duplicates_empty_db, - fixture: populated_db, - cmd: DuplicatesCmd { - module: None, - by_module: false, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // Result should be Detailed variant - match result { - DuplicatesOutput::Detailed(res) => { - // If there are no duplicates, we should have 0 groups - assert!(res.groups.is_empty() || !res.groups.is_empty()); - } - _ => panic!("Expected Detailed variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_with_module_filter, - fixture: populated_db, - cmd: DuplicatesCmd { - module: Some("MyApp".to_string()), - by_module: false, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::Detailed(res) => { - assert!(res.groups.is_empty() || !res.groups.is_empty()); - } - _ => panic!("Expected Detailed variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_with_exact_flag, - fixture: populated_db, - cmd: DuplicatesCmd { - module: None, - by_module: false, - exact: true, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::Detailed(res) => { - assert!(res.groups.is_empty() || !res.groups.is_empty()); - } - _ => panic!("Expected Detailed variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_with_regex_filter, - fixture: populated_db, - cmd: DuplicatesCmd { - module: Some("^MyApp\\.Controller$".to_string()), - by_module: false, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::Detailed(res) => { - assert!(res.groups.is_empty() || !res.groups.is_empty()); - } - _ => panic!("Expected Detailed variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_structure, - fixture: populated_db, - cmd: DuplicatesCmd { - module: None, - by_module: false, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::Detailed(res) => { - let _ = res.total_groups; - let _ = res.total_duplicates; - for group in &res.groups { - assert!(!group.hash.is_empty()); - assert!(group.functions.len() >= 2); - } - } - _ => panic!("Expected Detailed variant"), - } - }, - } - - // ========================================================================= - // By-module mode tests - // ========================================================================= - - crate::execute_test! { - test_name: test_duplicates_by_module, - fixture: populated_db, - cmd: DuplicatesCmd { - module: None, - by_module: true, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::ByModule(res) => { - let _ = res.total_modules; - let _ = res.total_duplicates; - for module in &res.modules { - assert!(!module.name.is_empty()); - assert!(module.duplicate_count > 0); - } - } - _ => panic!("Expected ByModule variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_by_module_with_filter, - fixture: populated_db, - cmd: DuplicatesCmd { - module: Some("MyApp".to_string()), - by_module: true, - exact: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::ByModule(res) => { - for module in &res.modules { - assert!(module.name.contains("MyApp")); - } - } - _ => panic!("Expected ByModule variant"), - } - }, - } - - crate::execute_test! { - test_name: test_duplicates_exclude_generated, - fixture: populated_db, - cmd: DuplicatesCmd { - module: None, - by_module: false, - exact: false, - exclude_generated: true, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - DuplicatesOutput::Detailed(res) => { - // With exclude_generated, generated functions should be filtered out - assert!(res.groups.is_empty() || !res.groups.is_empty()); - } - _ => panic!("Expected Detailed variant"), - } - }, - } -} diff --git a/src/commands/duplicates/mod.rs b/src/commands/duplicates/mod.rs deleted file mode 100644 index 08940b7..0000000 --- a/src/commands/duplicates/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions with identical or near-identical implementations -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search duplicates # Find all duplicate functions - code_search duplicates MyApp # Filter to specific module - code_search duplicates --by-module # Rank modules by duplication - code_search duplicates --exact # Use exact source matching - code_search duplicates --exclude-generated # Exclude macro-generated functions")] -pub struct DuplicatesCmd { - /// Module filter pattern (substring match by default, regex with -r) - pub module: Option, - - /// Aggregate results by module (show which modules have most duplicates) - #[arg(long)] - pub by_module: bool, - - /// Use exact source matching instead of AST matching - #[arg(long)] - pub exact: bool, - - /// Exclude macro-generated functions - #[arg(long)] - pub exclude_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for DuplicatesCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/duplicates/output.rs b/src/commands/duplicates/output.rs deleted file mode 100644 index d79a3fc..0000000 --- a/src/commands/duplicates/output.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::output::Outputable; - -use super::execute::{DuplicatesByModuleResult, DuplicatesOutput, DuplicatesResult}; - -impl Outputable for DuplicatesResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - lines.push("Duplicate Functions".to_string()); - lines.push(String::new()); - - if self.groups.is_empty() { - lines.push("No duplicate functions found.".to_string()); - } else { - lines.push(format!( - "Found {} group(s) of duplicate(s) ({} function(s) total):", - self.total_groups, self.total_duplicates - )); - lines.push(String::new()); - - for (idx, group) in self.groups.iter().enumerate() { - // Format hash - truncate for readability - let hash_display = if group.hash.len() > 20 { - format!("{}...", &group.hash[..17]) - } else { - group.hash.clone() - }; - - lines.push(format!( - "Group {} - hash:{}... ({} function(s)):", - idx + 1, - hash_display, - group.functions.len() - )); - - for func in &group.functions { - lines.push(format!( - " {}.{}/{} L{} {}", - func.module, func.name, func.arity, func.line, func.file - )); - } - lines.push(String::new()); - } - } - - lines.join("\n") - } -} - -impl Outputable for DuplicatesByModuleResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - lines.push("Modules with Most Duplicates".to_string()); - lines.push(String::new()); - - if self.modules.is_empty() { - lines.push("No duplicate functions found.".to_string()); - } else { - lines.push(format!( - "Found {} duplicated function(s) across {} module(s):", - self.total_duplicates, self.total_modules - )); - lines.push(String::new()); - - for module in &self.modules { - lines.push(format!("{} ({} duplicates):", module.name, module.duplicate_count)); - - for dup in &module.top_duplicates { - lines.push(format!( - " {}/{} ({} copies)", - dup.name, dup.arity, dup.copy_count - )); - } - lines.push(String::new()); - } - } - - lines.join("\n") - } -} - -impl Outputable for DuplicatesOutput { - fn to_table(&self) -> String { - match self { - DuplicatesOutput::Detailed(result) => result.to_table(), - DuplicatesOutput::ByModule(result) => result.to_table(), - } - } -} diff --git a/src/commands/duplicates/output_tests.rs b/src/commands/duplicates/output_tests.rs deleted file mode 100644 index 5758593..0000000 --- a/src/commands/duplicates/output_tests.rs +++ /dev/null @@ -1,541 +0,0 @@ -//! Output formatting tests for duplicates command. - -#[cfg(test)] -mod tests { - use super::super::execute::{ - DuplicateFunctionEntry, DuplicateGroup, DuplicateSummary, DuplicatesByModuleResult, - DuplicatesOutput, DuplicatesResult, ModuleDuplicates, - }; - use crate::output::{OutputFormat, Outputable}; - - #[test] - fn test_to_table_empty() { - let result = DuplicatesResult { - total_groups: 0, - total_duplicates: 0, - groups: vec![], - }; - - let output = result.to_table(); - assert!(output.contains("Duplicate Functions")); - assert!(output.contains("No duplicate functions found")); - } - - #[test] - fn test_to_table_single_group() { - let result = DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "abc123def456".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "MyApp.User".to_string(), - name: "validate".to_string(), - arity: 1, - line: 10, - file: "lib/my_app/user.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "MyApp.Post".to_string(), - name: "validate".to_string(), - arity: 1, - line: 15, - file: "lib/my_app/post.ex".to_string(), - }, - ], - }], - }; - - let output = result.to_table(); - assert!(output.contains("Duplicate Functions")); - assert!(output.contains("Found 1 group(s)")); - assert!(output.contains("MyApp.User.validate/1")); - assert!(output.contains("MyApp.Post.validate/1")); - assert!(output.contains("lib/my_app/user.ex")); - assert!(output.contains("lib/my_app/post.ex")); - } - - #[test] - fn test_to_table_multiple_groups() { - let result = DuplicatesResult { - total_groups: 2, - total_duplicates: 5, - groups: vec![ - DuplicateGroup { - hash: "hash_a".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "A".to_string(), - name: "f1".to_string(), - arity: 1, - line: 10, - file: "a.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "B".to_string(), - name: "f1".to_string(), - arity: 1, - line: 20, - file: "b.ex".to_string(), - }, - ], - }, - DuplicateGroup { - hash: "hash_b".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "C".to_string(), - name: "f2".to_string(), - arity: 2, - line: 30, - file: "c.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "D".to_string(), - name: "f2".to_string(), - arity: 2, - line: 40, - file: "d.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "E".to_string(), - name: "f2".to_string(), - arity: 2, - line: 50, - file: "e.ex".to_string(), - }, - ], - }, - ], - }; - - let output = result.to_table(); - assert!(output.contains("Found 2 group(s)")); - assert!(output.contains("5 function(s)")); - assert!(output.contains("Group 1")); - assert!(output.contains("Group 2")); - assert!(output.contains("A.f1/1")); - assert!(output.contains("C.f2/2")); - } - - #[test] - fn test_hash_truncation() { - let long_hash = "abcdefghijklmnopqrstuvwxyz1234567890"; - let result = DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: long_hash.to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "A".to_string(), - name: "f".to_string(), - arity: 0, - line: 1, - file: "a.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "B".to_string(), - name: "f".to_string(), - arity: 0, - line: 2, - file: "b.ex".to_string(), - }, - ], - }], - }; - - let output = result.to_table(); - // Hash should be truncated with "..." - assert!(output.contains("...")); - } - - #[test] - fn test_format_json() { - let result = DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "abc".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "M".to_string(), - name: "f".to_string(), - arity: 1, - line: 10, - file: "m.ex".to_string(), - }, - ], - }], - }; - - let output = result.format(OutputFormat::Json); - assert!(output.contains("total_groups")); - assert!(output.contains("total_duplicates")); - assert!(output.contains("groups")); - assert!(output.contains("\"hash\"")); - assert!(output.contains("\"functions\"")); - } - - #[test] - fn test_format_toon() { - let result = DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "abc".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "M".to_string(), - name: "f".to_string(), - arity: 1, - line: 10, - file: "m.ex".to_string(), - }, - ], - }], - }; - - let output = result.format(OutputFormat::Toon); - // Toon format should contain key parts - assert!(output.contains("total_groups")); - assert!(output.contains("1")); // count value - } - - #[test] - fn test_format_table() { - let result = DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "abc".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "M".to_string(), - name: "f".to_string(), - arity: 1, - line: 10, - file: "m.ex".to_string(), - }, - ], - }], - }; - - let output = result.format(OutputFormat::Table); - assert!(output.contains("Duplicate Functions")); - assert!(output.contains("M.f/1")); - } - - // ========================================================================= - // By-module output tests - // ========================================================================= - - #[test] - fn test_by_module_to_table_empty() { - let result = DuplicatesByModuleResult { - total_modules: 0, - total_duplicates: 0, - modules: vec![], - }; - - let output = result.to_table(); - assert!(output.contains("Modules with Most Duplicates")); - assert!(output.contains("No duplicate functions found")); - } - - #[test] - fn test_by_module_to_table_single() { - let result = DuplicatesByModuleResult { - total_modules: 1, - total_duplicates: 3, - modules: vec![ModuleDuplicates { - name: "MyApp.Utils".to_string(), - duplicate_count: 3, - top_duplicates: vec![ - DuplicateSummary { - name: "validate".to_string(), - arity: 1, - copy_count: 2, - }, - DuplicateSummary { - name: "format".to_string(), - arity: 2, - copy_count: 1, - }, - ], - }], - }; - - let output = result.to_table(); - assert!(output.contains("Modules with Most Duplicates")); - assert!(output.contains("Found 3 duplicated function(s) across 1 module(s)")); - assert!(output.contains("MyApp.Utils (3 duplicates)")); - assert!(output.contains("validate/1 (2 copies)")); - assert!(output.contains("format/2 (1 copies)")); - } - - #[test] - fn test_by_module_to_table_multiple() { - let result = DuplicatesByModuleResult { - total_modules: 2, - total_duplicates: 5, - modules: vec![ - ModuleDuplicates { - name: "MyApp.Users".to_string(), - duplicate_count: 3, - top_duplicates: vec![DuplicateSummary { - name: "validate".to_string(), - arity: 1, - copy_count: 3, - }], - }, - ModuleDuplicates { - name: "MyApp.Posts".to_string(), - duplicate_count: 2, - top_duplicates: vec![DuplicateSummary { - name: "format".to_string(), - arity: 0, - copy_count: 2, - }], - }, - ], - }; - - let output = result.to_table(); - assert!(output.contains("Found 5 duplicated function(s) across 2 module(s)")); - assert!(output.contains("MyApp.Users (3 duplicates)")); - assert!(output.contains("MyApp.Posts (2 duplicates)")); - } - - #[test] - fn test_by_module_format_json() { - let result = DuplicatesByModuleResult { - total_modules: 1, - total_duplicates: 2, - modules: vec![ModuleDuplicates { - name: "MyApp".to_string(), - duplicate_count: 2, - top_duplicates: vec![DuplicateSummary { - name: "f".to_string(), - arity: 1, - copy_count: 2, - }], - }], - }; - - let output = result.format(OutputFormat::Json); - assert!(output.contains("\"total_modules\"")); - assert!(output.contains("\"total_duplicates\"")); - assert!(output.contains("\"modules\"")); - assert!(output.contains("\"name\"")); - assert!(output.contains("\"duplicate_count\"")); - assert!(output.contains("\"top_duplicates\"")); - assert!(output.contains("\"copy_count\"")); - } - - #[test] - fn test_by_module_format_toon() { - let result = DuplicatesByModuleResult { - total_modules: 1, - total_duplicates: 2, - modules: vec![ModuleDuplicates { - name: "MyApp".to_string(), - duplicate_count: 2, - top_duplicates: vec![DuplicateSummary { - name: "f".to_string(), - arity: 1, - copy_count: 2, - }], - }], - }; - - let output = result.format(OutputFormat::Toon); - assert!(output.contains("total_modules")); - assert!(output.contains("total_duplicates")); - } - - // ========================================================================= - // DuplicatesOutput enum tests - // ========================================================================= - - #[test] - fn test_output_enum_detailed_empty() { - let result = DuplicatesOutput::Detailed(DuplicatesResult { - total_groups: 0, - total_duplicates: 0, - groups: vec![], - }); - - let output = result.to_table(); - assert!(output.contains("Duplicate Functions")); - assert!(output.contains("No duplicate functions found")); - } - - #[test] - fn test_output_enum_by_module_empty() { - let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { - total_modules: 0, - total_duplicates: 0, - modules: vec![], - }); - - let output = result.to_table(); - assert!(output.contains("Modules with Most Duplicates")); - assert!(output.contains("No duplicate functions found")); - } - - #[test] - fn test_output_enum_detailed_with_data() { - let result = DuplicatesOutput::Detailed(DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "abc123".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "MyApp.User".to_string(), - name: "validate".to_string(), - arity: 1, - line: 10, - file: "lib/user.ex".to_string(), - }, - DuplicateFunctionEntry { - module: "MyApp.Post".to_string(), - name: "validate".to_string(), - arity: 1, - line: 20, - file: "lib/post.ex".to_string(), - }, - ], - }], - }); - - // Table format - let table = result.to_table(); - assert!(table.contains("Duplicate Functions")); - assert!(table.contains("Found 1 group(s)")); - assert!(table.contains("MyApp.User.validate/1")); - assert!(table.contains("MyApp.Post.validate/1")); - - // JSON format - let json = result.format(OutputFormat::Json); - assert!(json.contains("\"total_groups\": 1")); - assert!(json.contains("\"total_duplicates\": 2")); - assert!(json.contains("\"hash\": \"abc123\"")); - assert!(json.contains("\"module\": \"MyApp.User\"")); - - // Toon format - let toon = result.format(OutputFormat::Toon); - assert!(toon.contains("total_groups")); - assert!(toon.contains("groups")); - } - - #[test] - fn test_output_enum_by_module_with_data() { - let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { - total_modules: 2, - total_duplicates: 5, - modules: vec![ - ModuleDuplicates { - name: "MyApp.Users".to_string(), - duplicate_count: 3, - top_duplicates: vec![DuplicateSummary { - name: "validate".to_string(), - arity: 1, - copy_count: 3, - }], - }, - ModuleDuplicates { - name: "MyApp.Posts".to_string(), - duplicate_count: 2, - top_duplicates: vec![DuplicateSummary { - name: "format".to_string(), - arity: 0, - copy_count: 2, - }], - }, - ], - }); - - // Table format - let table = result.to_table(); - assert!(table.contains("Modules with Most Duplicates")); - assert!(table.contains("Found 5 duplicated function(s) across 2 module(s)")); - assert!(table.contains("MyApp.Users (3 duplicates)")); - assert!(table.contains("MyApp.Posts (2 duplicates)")); - - // JSON format - let json = result.format(OutputFormat::Json); - assert!(json.contains("\"total_modules\": 2")); - assert!(json.contains("\"total_duplicates\": 5")); - assert!(json.contains("\"name\": \"MyApp.Users\"")); - assert!(json.contains("\"duplicate_count\": 3")); - - // Toon format - let toon = result.format(OutputFormat::Toon); - assert!(toon.contains("total_modules")); - assert!(toon.contains("modules")); - } - - #[test] - fn test_output_enum_detailed_json_structure() { - let result = DuplicatesOutput::Detailed(DuplicatesResult { - total_groups: 1, - total_duplicates: 2, - groups: vec![DuplicateGroup { - hash: "test_hash".to_string(), - functions: vec![ - DuplicateFunctionEntry { - module: "A".to_string(), - name: "func".to_string(), - arity: 0, - line: 1, - file: "a.ex".to_string(), - }, - ], - }], - }); - - let json = result.format(OutputFormat::Json); - // Verify JSON structure has expected fields - assert!(json.contains("\"total_groups\"")); - assert!(json.contains("\"total_duplicates\"")); - assert!(json.contains("\"groups\"")); - assert!(json.contains("\"hash\"")); - assert!(json.contains("\"functions\"")); - assert!(json.contains("\"module\"")); - assert!(json.contains("\"name\"")); - assert!(json.contains("\"arity\"")); - assert!(json.contains("\"line\"")); - assert!(json.contains("\"file\"")); - } - - #[test] - fn test_output_enum_by_module_json_structure() { - let result = DuplicatesOutput::ByModule(DuplicatesByModuleResult { - total_modules: 1, - total_duplicates: 2, - modules: vec![ModuleDuplicates { - name: "TestModule".to_string(), - duplicate_count: 2, - top_duplicates: vec![DuplicateSummary { - name: "func".to_string(), - arity: 1, - copy_count: 2, - }], - }], - }); - - let json = result.format(OutputFormat::Json); - // Verify JSON structure has expected fields - assert!(json.contains("\"total_modules\"")); - assert!(json.contains("\"total_duplicates\"")); - assert!(json.contains("\"modules\"")); - assert!(json.contains("\"name\"")); - assert!(json.contains("\"duplicate_count\"")); - assert!(json.contains("\"top_duplicates\"")); - assert!(json.contains("\"arity\"")); - assert!(json.contains("\"copy_count\"")); - } -} diff --git a/src/commands/function/cli_tests.rs b/src/commands/function/cli_tests.rs deleted file mode 100644 index 7fd81c9..0000000 --- a/src/commands/function/cli_tests.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! CLI parsing tests for function command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "function", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_required_arg_test! { - command: "function", - test_name: test_requires_function, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "function", - variant: Function, - test_name: test_with_module_and_function, - args: ["MyApp.Accounts", "get_user"], - field: module, - expected: "MyApp.Accounts", - } - - crate::cli_option_test! { - command: "function", - variant: Function, - test_name: test_function_name, - args: ["MyApp.Accounts", "get_user"], - field: function, - expected: "get_user", - } - - crate::cli_option_test! { - command: "function", - variant: Function, - test_name: test_with_arity, - args: ["MyApp.Accounts", "get_user", "--arity", "1"], - field: arity, - expected: Some(1), - } - - crate::cli_option_test! { - command: "function", - variant: Function, - test_name: test_with_regex, - args: ["MyApp.*", "get_.*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "function", - variant: Function, - test_name: test_with_limit, - args: ["MyApp", "foo", "--limit", "50"], - field: common.limit, - expected: 50, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "function", - variant: Function, - required_args: ["MyApp", "foo"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/function/execute.rs b/src/commands/function/execute.rs deleted file mode 100644 index f14fdbb..0000000 --- a/src/commands/function/execute.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::FunctionCmd; -use crate::commands::Execute; -use crate::queries::function::{find_functions, FunctionSignature}; -use crate::types::ModuleGroupResult; - -/// A function signature within a module -#[derive(Debug, Clone, Serialize)] -pub struct FuncSig { - pub name: String, - pub arity: i64, - #[serde(skip_serializing_if = "String::is_empty")] - pub args: String, - #[serde(skip_serializing_if = "String::is_empty")] - pub return_type: String, -} - -impl ModuleGroupResult { - /// Build grouped result from flat FunctionSignature list - fn from_signatures( - module_pattern: String, - function_pattern: String, - signatures: Vec, - ) -> Self { - let total_items = signatures.len(); - - // Use helper to group by module - let items = crate::utils::group_by_module(signatures, |sig| { - let func_sig = FuncSig { - name: sig.name, - arity: sig.arity, - args: sig.args, - return_type: sig.return_type, - }; - // File is intentionally empty for functions because the function command - // queries the functions table which doesn't track file locations. - // File locations are available in function_locations table if needed. - (sig.module, func_sig) - }); - - ModuleGroupResult { - module_pattern, - function_pattern: Some(function_pattern), - total_items, - items, - } - } -} - -impl Execute for FunctionCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let signatures = find_functions( - db, - &self.module, - &self.function, - self.arity, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(>::from_signatures( - self.module, - self.function, - signatures, - )) - } -} diff --git a/src/commands/function/execute_tests.rs b/src/commands/function/execute_tests.rs deleted file mode 100644 index 1e29aaf..0000000 --- a/src/commands/function/execute_tests.rs +++ /dev/null @@ -1,160 +0,0 @@ -//! Execute tests for function command. - -#[cfg(test)] -mod tests { - use super::super::FunctionCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: type_signatures, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // MyApp.Accounts has 2 get_user functions (arity 1 and 2) - crate::execute_test! { - test_name: test_function_exact_match, - fixture: populated_db, - cmd: FunctionCmd { - module: "MyApp.Accounts".to_string(), - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2); - assert_eq!(result.items.len(), 1); - assert_eq!(result.items[0].entries.len(), 2); - }, - } - - crate::execute_test! { - test_name: test_function_with_arity, - fixture: populated_db, - cmd: FunctionCmd { - module: "MyApp.Accounts".to_string(), - function: "get_user".to_string(), - arity: Some(1), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 1); - let func = &result.items[0].entries[0]; - assert_eq!(func.arity, 1); - assert_eq!(func.args, "integer()"); - assert_eq!(func.return_type, "User.t() | nil"); - }, - } - - // Functions containing "user": get_user/1, get_user/2, list_users, create_user = 4 - crate::execute_test! { - test_name: test_function_regex_match, - fixture: populated_db, - cmd: FunctionCmd { - module: "MyApp\\..*".to_string(), - function: ".*user.*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 4); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_function_no_match, - fixture: populated_db, - cmd: FunctionCmd { - module: "NonExistent".to_string(), - function: "foo".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: items, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_function_with_project_filter, - fixture: populated_db, - cmd: FunctionCmd { - module: "MyApp.Accounts".to_string(), - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.items.len(), 1); - assert_eq!(result.items[0].name, "MyApp.Accounts"); - }, - } - - crate::execute_test! { - test_name: test_function_with_limit, - fixture: populated_db, - cmd: FunctionCmd { - module: "MyApp\\..*".to_string(), - function: ".*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 2, - }, - }, - assertions: |result| { - // Limit applies to raw results before grouping - assert_eq!(result.total_items, 2); - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: FunctionCmd, - cmd: FunctionCmd { - module: "MyApp".to_string(), - function: "foo".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/function/mod.rs b/src/commands/function/mod.rs deleted file mode 100644 index a2b21e5..0000000 --- a/src/commands/function/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Show function signature (args, return type) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search function MyApp.Accounts get_user # Show signature - code_search function MyApp.Accounts get_user -a 1 # Specific arity - code_search function -r 'MyApp\\..*' 'get_.*' # Regex matching -")] -pub struct FunctionCmd { - /// Module name (exact match or pattern with --regex) - pub module: String, - - /// Function name (exact match or pattern with --regex) - pub function: String, - - /// Function arity (optional, matches all arities if not specified) - #[arg(short, long)] - pub arity: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for FunctionCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/function/output.rs b/src/commands/function/output.rs deleted file mode 100644 index dffa742..0000000 --- a/src/commands/function/output.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! Output formatting for function command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::FuncSig; - -impl TableFormatter for ModuleGroupResult { - type Entry = FuncSig; - - fn format_header(&self) -> String { - let function_pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); - format!("Function: {}.{}", self.module_pattern, function_pattern) - } - - fn format_empty_message(&self) -> String { - "No functions found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} signature(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, func: &FuncSig, _module: &str, _file: &str) -> String { - format!("{}/{}", func.name, func.arity) - } - - fn format_entry_details(&self, func: &FuncSig, _module: &str, _file: &str) -> Vec { - let mut details = Vec::new(); - if !func.args.is_empty() { - details.push(format!("args: {}", func.args)); - } - if !func.return_type.is_empty() { - details.push(format!("returns: {}", func.return_type)); - } - details - } -} diff --git a/src/commands/function/output_tests.rs b/src/commands/function/output_tests.rs deleted file mode 100644 index 86aec7f..0000000 --- a/src/commands/function/output_tests.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! Output formatting tests for function command. - -#[cfg(test)] -mod tests { - use super::super::execute::FuncSig; - use crate::types::{ModuleGroupResult, ModuleGroup}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Function: MyApp.Accounts.get_user - -No functions found."; - - const SINGLE_TABLE: &str = "\ -Function: MyApp.Accounts.get_user - -Found 1 signature(s) in 1 module(s): - -MyApp.Accounts: - get_user/1 - args: integer() - returns: User.t() | nil"; - - const MULTIPLE_TABLE: &str = "\ -Function: MyApp.Accounts.get_user - -Found 2 signature(s) in 1 module(s): - -MyApp.Accounts: - get_user/1 - args: integer() - returns: User.t() | nil - get_user/2 - args: integer(), keyword() - returns: User.t() | nil"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Accounts".to_string(), - function_pattern: Some("get_user".to_string()), - total_items: 0, - items: vec![], - } - } - - #[fixture] - fn single_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Accounts".to_string(), - function_pattern: Some("get_user".to_string()), - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: String::new(), - entries: vec![FuncSig { - name: "get_user".to_string(), - arity: 1, - args: "integer()".to_string(), - return_type: "User.t() | nil".to_string(), - }], - function_count: None, - }], - } - } - - #[fixture] - fn multiple_result() -> ModuleGroupResult { - ModuleGroupResult { - module_pattern: "MyApp.Accounts".to_string(), - function_pattern: Some("get_user".to_string()), - total_items: 2, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: String::new(), - entries: vec![ - FuncSig { - name: "get_user".to_string(), - arity: 1, - args: "integer()".to_string(), - return_type: "User.t() | nil".to_string(), - }, - FuncSig { - name: "get_user".to_string(), - arity: 2, - args: "integer(), keyword()".to_string(), - return_type: "User.t() | nil".to_string(), - }, - ], - function_count: None, - }], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: ModuleGroupResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleGroupResult, - expected: crate::test_utils::load_output_fixture("function", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/god_modules/execute.rs b/src/commands/god_modules/execute.rs deleted file mode 100644 index cf4ee0d..0000000 --- a/src/commands/god_modules/execute.rs +++ /dev/null @@ -1,164 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::GodModulesCmd; -use crate::commands::Execute; -use crate::queries::hotspots::{find_hotspots, get_function_counts, get_module_loc, HotspotKind}; -use crate::types::{ModuleCollectionResult, ModuleGroup}; - -/// A single god module entry -#[derive(Debug, Clone, Serialize)] -pub struct GodModuleEntry { - pub function_count: i64, - pub loc: i64, - pub incoming: i64, - pub outgoing: i64, - pub total: i64, -} - -impl Execute for GodModulesCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - // Get function counts for all modules - let func_counts = get_function_counts( - db, - &self.common.project, - self.module.as_deref(), - self.common.regex, - )?; - - // Get lines of code per module - let module_loc = get_module_loc( - db, - &self.common.project, - self.module.as_deref(), - self.common.regex, - )?; - - // Get hotspot data (incoming/outgoing calls per function) - let hotspots = find_hotspots( - db, - HotspotKind::Total, - self.module.as_deref(), - &self.common.project, - self.common.regex, - u32::MAX, // Get all hotspots to aggregate connectivity - false, // Don't exclude generated functions - false, // Don't require outgoing calls - )?; - - // Aggregate connectivity (incoming/outgoing) per module - let mut module_connectivity: std::collections::HashMap = - std::collections::HashMap::new(); - - for hotspot in hotspots { - let entry = module_connectivity - .entry(hotspot.module) - .or_insert((0, 0)); - entry.0 += hotspot.incoming; - entry.1 += hotspot.outgoing; - } - - // Build god modules: filter by thresholds and sort by total connectivity - // Tuple: (module_name, func_count, loc, incoming, outgoing) - let mut god_modules: Vec<(String, i64, i64, i64, i64)> = Vec::new(); - - for (module_name, func_count) in func_counts { - // Apply function count threshold - if func_count < self.min_functions { - continue; - } - - // Get LoC for this module - let loc = module_loc.get(&module_name).copied().unwrap_or(0); - - // Apply LoC threshold if set - if loc < self.min_loc { - continue; - } - - // Get connectivity for this module - let (incoming, outgoing) = module_connectivity - .get(&module_name) - .copied() - .unwrap_or((0, 0)); - let total = incoming + outgoing; - - // Apply total connectivity threshold - if total < self.min_total { - continue; - } - - god_modules.push((module_name, func_count, loc, incoming, outgoing)); - } - - // Sort by total connectivity (descending) - god_modules.sort_by(|a, b| { - let total_a = a.3 + a.4; - let total_b = b.3 + b.4; - total_b.cmp(&total_a) - }); - - // Apply limit - let limit = self.common.limit as usize; - god_modules.truncate(limit); - - // Convert to ModuleGroup entries - let total_items = god_modules.len(); - let items: Vec> = god_modules - .into_iter() - .map(|(module_name, func_count, loc, incoming, outgoing)| { - let total = incoming + outgoing; - ModuleGroup { - name: module_name, - file: String::new(), - entries: vec![GodModuleEntry { - function_count: func_count, - loc, - incoming, - outgoing, - total, - }], - function_count: Some(func_count), - } - }) - .collect(); - - Ok(ModuleCollectionResult { - module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), - function_pattern: None, - kind_filter: Some("god".to_string()), - name_filter: None, - total_items, - items, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_god_modules_cmd_structure() { - // Test that GodModulesCmd is created correctly - let cmd = GodModulesCmd { - min_functions: 30, - min_loc: 500, - min_total: 15, - module: Some("MyApp".to_string()), - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 20, - }, - }; - - assert_eq!(cmd.min_functions, 30); - assert_eq!(cmd.min_loc, 500); - assert_eq!(cmd.min_total, 15); - assert_eq!(cmd.module, Some("MyApp".to_string())); - } -} diff --git a/src/commands/god_modules/mod.rs b/src/commands/god_modules/mod.rs deleted file mode 100644 index 809b4f6..0000000 --- a/src/commands/god_modules/mod.rs +++ /dev/null @@ -1,51 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find god modules - modules with high function count and high connectivity -/// -/// God modules are those with many functions and high incoming/outgoing call counts, -/// indicating they have too many responsibilities. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search god-modules # Find all god modules - code_search god-modules MyApp.Core # Filter to MyApp.Core namespace - code_search god-modules --min-functions 30 # With minimum 30 functions - code_search god-modules --min-loc 500 # With minimum 500 lines of code - code_search god-modules --min-total 15 # With minimum 15 total connectivity - code_search god-modules -l 20 # Show top 20 god modules -")] -pub struct GodModulesCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Minimum function count to be considered a god module - #[arg(long, default_value = "20")] - pub min_functions: i64, - - /// Minimum lines of code to be considered a god module - #[arg(long, default_value = "0")] - pub min_loc: i64, - - /// Minimum total connectivity (incoming + outgoing) to be considered a god module - #[arg(long, default_value = "10")] - pub min_total: i64, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for GodModulesCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/god_modules/output.rs b/src/commands/god_modules/output.rs deleted file mode 100644 index 678d811..0000000 --- a/src/commands/god_modules/output.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! Output formatting for god modules command results. - -use super::execute::GodModuleEntry; -use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; - -impl TableFormatter for ModuleCollectionResult { - type Entry = GodModuleEntry; - - fn format_header(&self) -> String { - "God Modules".to_string() - } - - fn format_empty_message(&self) -> String { - "No god modules found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} god module(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_module_header_with_entries( - &self, - module_name: &str, - _module_file: &str, - entries: &[GodModuleEntry], - ) -> String { - if let Some(entry) = entries.first() { - format!( - "{}: (funcs: {}, loc: {}, in: {}, out: {}, total: {})", - module_name, entry.function_count, entry.loc, entry.incoming, entry.outgoing, entry.total - ) - } else { - format!("{}:", module_name) - } - } - - fn format_entry(&self, _entry: &GodModuleEntry, _module: &str, _file: &str) -> String { - // For god modules, we don't show individual entries since each module has only one entry - // The module header already shows all the stats - String::new() - } - - fn blank_before_module(&self) -> bool { - true - } - - fn blank_after_summary(&self) -> bool { - false - } -} diff --git a/src/commands/hotspots/cli_tests.rs b/src/commands/hotspots/cli_tests.rs deleted file mode 100644 index 6ff3c65..0000000 --- a/src/commands/hotspots/cli_tests.rs +++ /dev/null @@ -1,133 +0,0 @@ -//! CLI parsing tests for hotspots command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use crate::queries::hotspots::HotspotKind; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - // Test default values - crate::cli_defaults_test! { - command: "hotspots", - variant: Hotspots, - required_args: [], - defaults: { - common.project: "default", - common.regex: false, - common.limit: 100, - exclude_generated: false, - }, - } - - // Test positional module argument - crate::cli_option_test! { - command: "hotspots", - variant: Hotspots, - test_name: test_with_module, - args: ["MyApp"], - field: module, - expected: Some("MyApp".to_string()), - } - - crate::cli_option_test! { - command: "hotspots", - variant: Hotspots, - test_name: test_with_project, - args: ["--project", "my_app"], - field: common.project, - expected: "my_app", - } - - crate::cli_option_test! { - command: "hotspots", - variant: Hotspots, - test_name: test_with_regex, - args: ["MyApp\\..*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "hotspots", - variant: Hotspots, - test_name: test_with_limit, - args: ["--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_option_test! { - command: "hotspots", - variant: Hotspots, - test_name: test_with_exclude_generated, - args: ["--exclude-generated"], - field: exclude_generated, - expected: true, - } - - // Test limit validation - crate::cli_limit_tests! { - command: "hotspots", - variant: Hotspots, - required_args: [], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Kind option tests - // ========================================================================= - - #[rstest] - fn test_kind_default_is_incoming() { - let args = Args::try_parse_from(["code_search", "hotspots"]).unwrap(); - match args.command { - crate::commands::Command::Hotspots(cmd) => { - assert!(matches!(cmd.kind, HotspotKind::Incoming)); - } - _ => panic!("Expected Hotspots command"), - } - } - - #[rstest] - fn test_kind_outgoing() { - let args = - Args::try_parse_from(["code_search", "hotspots", "--kind", "outgoing"]).unwrap(); - match args.command { - crate::commands::Command::Hotspots(cmd) => { - assert!(matches!(cmd.kind, HotspotKind::Outgoing)); - } - _ => panic!("Expected Hotspots command"), - } - } - - #[rstest] - fn test_kind_total() { - let args = Args::try_parse_from(["code_search", "hotspots", "--kind", "total"]).unwrap(); - match args.command { - crate::commands::Command::Hotspots(cmd) => { - assert!(matches!(cmd.kind, HotspotKind::Total)); - } - _ => panic!("Expected Hotspots command"), - } - } - - #[rstest] - fn test_kind_ratio() { - let args = Args::try_parse_from(["code_search", "hotspots", "--kind", "ratio"]).unwrap(); - match args.command { - crate::commands::Command::Hotspots(cmd) => { - assert!(matches!(cmd.kind, HotspotKind::Ratio)); - } - _ => panic!("Expected Hotspots command"), - } - } -} diff --git a/src/commands/hotspots/execute.rs b/src/commands/hotspots/execute.rs deleted file mode 100644 index 5d8ca38..0000000 --- a/src/commands/hotspots/execute.rs +++ /dev/null @@ -1,142 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::HotspotsCmd; -use crate::commands::Execute; -use crate::output::Outputable; -use crate::queries::hotspots::find_hotspots; - -/// A function hotspot entry -#[derive(Debug, Clone, Serialize)] -pub struct FunctionHotspotEntry { - pub module: String, - pub function: String, - pub incoming: i64, - pub outgoing: i64, - pub total: i64, - pub ratio: f64, -} - -/// Result type for hotspots command -#[derive(Debug, Serialize)] -pub struct HotspotsResult { - pub kind: String, - pub total_items: usize, - pub entries: Vec, -} - -impl Outputable for HotspotsResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - lines.push(format!("Hotspots ({})", self.kind)); - lines.push(String::new()); - - if self.entries.is_empty() { - lines.push("No hotspots found.".to_string()); - return lines.join("\n"); - } - - let item_word = if self.total_items == 1 { - "function" - } else { - "functions" - }; - lines.push(format!("Found {} {}:", self.total_items, item_word)); - lines.push(String::new()); - - // Calculate column widths for alignment - let name_width = self - .entries - .iter() - .map(|e| e.module.len() + 1 + e.function.len()) - .max() - .unwrap_or(0); - let in_width = self - .entries - .iter() - .map(|e| e.incoming.to_string().len()) - .max() - .unwrap_or(0); - let out_width = self - .entries - .iter() - .map(|e| e.outgoing.to_string().len()) - .max() - .unwrap_or(0); - let total_width = self - .entries - .iter() - .map(|e| e.total.to_string().len()) - .max() - .unwrap_or(0); - - for entry in &self.entries { - let name = format!("{}.{}", entry.module, entry.function); - let ratio_str = if entry.ratio >= 9999.0 { - "∞".to_string() - } else { - format!("{:.2}", entry.ratio) - }; - lines.push(format!( - "{:in_width$} in {:>out_width$} out {:>total_width$} total {:>6} ratio", - name, - entry.incoming, - entry.outgoing, - entry.total, - ratio_str, - name_width = name_width, - in_width = in_width, - out_width = out_width, - total_width = total_width, - )); - } - - lines.join("\n") - } -} - -impl Execute for HotspotsCmd { - type Output = HotspotsResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let hotspots = find_hotspots( - db, - self.kind, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.common.limit, - self.exclude_generated, - false, // Don't require outgoing calls - )?; - - let kind_str = match self.kind { - crate::queries::hotspots::HotspotKind::Incoming => "incoming", - crate::queries::hotspots::HotspotKind::Outgoing => "outgoing", - crate::queries::hotspots::HotspotKind::Total => "total", - crate::queries::hotspots::HotspotKind::Ratio => "ratio", - }; - - let entries: Vec = hotspots - .into_iter() - .map(|hotspot| FunctionHotspotEntry { - module: hotspot.module, - function: hotspot.function, - incoming: hotspot.incoming, - outgoing: hotspot.outgoing, - total: hotspot.total, - ratio: hotspot.ratio, - }) - .collect(); - - let total_items = entries.len(); - - Ok(HotspotsResult { - kind: kind_str.to_string(), - total_items, - entries, - }) - } -} diff --git a/src/commands/hotspots/execute_tests.rs b/src/commands/hotspots/execute_tests.rs deleted file mode 100644 index 38af50b..0000000 --- a/src/commands/hotspots/execute_tests.rs +++ /dev/null @@ -1,170 +0,0 @@ -//! Execute tests for hotspots command. - -#[cfg(test)] -mod tests { - use super::super::HotspotsCmd; - use crate::commands::CommonArgs; - use crate::commands::Execute; - use crate::queries::hotspots::HotspotKind; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - #[rstest] - fn test_hotspots_incoming(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Incoming, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - assert_eq!(result.kind, "incoming"); - assert!(!result.entries.is_empty()); - } - - #[rstest] - fn test_hotspots_outgoing(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Outgoing, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - assert_eq!(result.kind, "outgoing"); - assert!(!result.entries.is_empty()); - } - - #[rstest] - fn test_hotspots_total(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Total, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - assert_eq!(result.kind, "total"); - assert!(!result.entries.is_empty()); - } - - #[rstest] - fn test_hotspots_ratio(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Ratio, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - assert_eq!(result.kind, "ratio"); - assert!(!result.entries.is_empty()); - // All entries should have a ratio value - assert!(result.entries.iter().all(|e| e.ratio >= 0.0)); - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - #[rstest] - fn test_hotspots_with_module_filter(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: Some("Accounts".to_string()), - kind: HotspotKind::Incoming, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - // All entries should have Accounts in the module name - assert!(result.entries.iter().all(|e| e.module.contains("Accounts"))); - } - - #[rstest] - fn test_hotspots_with_limit(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Incoming, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 2, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - assert!(result.entries.len() <= 2); - } - - #[rstest] - fn test_hotspots_exclude_generated(populated_db: cozo::DbInstance) { - let cmd = HotspotsCmd { - module: None, - kind: HotspotKind::Incoming, - exclude_generated: true, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }; - let result = cmd.execute(&populated_db).expect("Execute should succeed"); - - // With exclude_generated, generated functions should be filtered out - // Result may or may not be empty depending on test data - assert_eq!(result.kind, "incoming"); - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: HotspotsCmd, - cmd: HotspotsCmd { - module: None, - kind: HotspotKind::Incoming, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 20, - }, - }, - } -} diff --git a/src/commands/hotspots/mod.rs b/src/commands/hotspots/mod.rs deleted file mode 100644 index 7dc4ad7..0000000 --- a/src/commands/hotspots/mod.rs +++ /dev/null @@ -1,56 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; -use crate::queries::hotspots::HotspotKind; - -/// Find functions with the most incoming/outgoing calls -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search hotspots # Most called functions (incoming) - code_search hotspots -k outgoing # Functions that call many others - code_search hotspots -k total # Highest total connections - code_search hotspots -k ratio # Boundary functions (high incoming/outgoing ratio) - code_search hotspots MyApp -l 10 # Top 10 in MyApp namespace - code_search hotspots --exclude-generated # Exclude macro-generated functions - - # Find wide functions (high fan-out): - code_search hotspots -k outgoing -l 20 # Top 20 functions calling many others - - # Find deep functions (high fan-in): - code_search hotspots -k incoming -l 20 # Top 20 most-called functions - - # Find boundary functions (many callers, few dependencies): - code_search hotspots -k ratio -l 20 # Top 20 boundary functions")] -pub struct HotspotsCmd { - /// Module pattern to filter results (substring match by default, regex with --regex) - pub module: Option, - - /// Type of hotspots to find - #[arg(short, long, value_enum, default_value_t = HotspotKind::Incoming)] - pub kind: HotspotKind, - - /// Exclude macro-generated functions - #[arg(long)] - pub exclude_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for HotspotsCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/hotspots/output.rs b/src/commands/hotspots/output.rs deleted file mode 100644 index 2bff26c..0000000 --- a/src/commands/hotspots/output.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Output formatting for hotspots command results. - -// Output formatting is now handled directly in execute.rs via the Outputable trait -// implementations for FunctionHotspotsResult and ModuleHotspotsResult. diff --git a/src/commands/hotspots/output_tests.rs b/src/commands/hotspots/output_tests.rs deleted file mode 100644 index eaba383..0000000 --- a/src/commands/hotspots/output_tests.rs +++ /dev/null @@ -1,153 +0,0 @@ -//! Output formatting tests for hotspots command. - -#[cfg(test)] -mod tests { - use super::super::execute::{FunctionHotspotEntry, HotspotsResult}; - use crate::output::{OutputFormat, Outputable}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Hotspots (incoming) - -No hotspots found."; - - const SINGLE_TABLE: &str = "\ -Hotspots (total) - -Found 1 function: - -MyApp.Accounts.get_user 3 in 1 out 4 total 0.25 ratio"; - - const MULTIPLE_TABLE: &str = "\ -Hotspots (incoming) - -Found 2 functions: - -MyApp.Accounts.get_user 10 in 2 out 12 total 0.17 ratio -MyApp.Users.create 5 in 3 out 8 total 0.38 ratio"; - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> HotspotsResult { - HotspotsResult { - kind: "incoming".to_string(), - total_items: 0, - entries: vec![], - } - } - - #[fixture] - fn single_result() -> HotspotsResult { - HotspotsResult { - kind: "total".to_string(), - total_items: 1, - entries: vec![FunctionHotspotEntry { - module: "MyApp.Accounts".to_string(), - function: "get_user".to_string(), - incoming: 3, - outgoing: 1, - total: 4, - ratio: 0.25, - }], - } - } - - #[fixture] - fn multiple_result() -> HotspotsResult { - HotspotsResult { - kind: "incoming".to_string(), - total_items: 2, - entries: vec![ - FunctionHotspotEntry { - module: "MyApp.Accounts".to_string(), - function: "get_user".to_string(), - incoming: 10, - outgoing: 2, - total: 12, - ratio: 0.17, - }, - FunctionHotspotEntry { - module: "MyApp.Users".to_string(), - function: "create".to_string(), - incoming: 5, - outgoing: 3, - total: 8, - ratio: 0.38, - }, - ], - } - } - - // ========================================================================= - // Table format tests - // ========================================================================= - - #[rstest] - fn test_to_table_empty(empty_result: HotspotsResult) { - let output = empty_result.to_table(); - assert_eq!(output, EMPTY_TABLE); - } - - #[rstest] - fn test_to_table_single(single_result: HotspotsResult) { - let output = single_result.to_table(); - assert_eq!(output, SINGLE_TABLE); - } - - #[rstest] - fn test_to_table_multiple(multiple_result: HotspotsResult) { - let output = multiple_result.to_table(); - assert_eq!(output, MULTIPLE_TABLE); - } - - // ========================================================================= - // JSON format tests - // ========================================================================= - - #[rstest] - fn test_format_json(single_result: HotspotsResult) { - let output = single_result.format(OutputFormat::Json); - assert!(output.contains("\"kind\": \"total\"")); - assert!(output.contains("\"total_items\": 1")); - assert!(output.contains("\"entries\"")); - assert!(output.contains("\"module\": \"MyApp.Accounts\"")); - assert!(output.contains("\"function\": \"get_user\"")); - assert!(output.contains("\"incoming\": 3")); - assert!(output.contains("\"outgoing\": 1")); - assert!(output.contains("\"total\": 4")); - } - - #[rstest] - fn test_format_json_empty(empty_result: HotspotsResult) { - let output = empty_result.format(OutputFormat::Json); - assert!(output.contains("\"kind\": \"incoming\"")); - assert!(output.contains("\"total_items\": 0")); - assert!(output.contains("\"entries\": []")); - } - - // ========================================================================= - // Toon format tests - // ========================================================================= - - #[rstest] - fn test_format_toon(single_result: HotspotsResult) { - let output = single_result.format(OutputFormat::Toon); - assert!(output.contains("kind")); - assert!(output.contains("total_items")); - assert!(output.contains("entries")); - } - - #[rstest] - fn test_format_toon_empty(empty_result: HotspotsResult) { - let output = empty_result.format(OutputFormat::Toon); - assert!(output.contains("kind")); - assert!(output.contains("entries")); - } -} diff --git a/src/commands/import/cli_tests.rs b/src/commands/import/cli_tests.rs deleted file mode 100644 index 2d1dca0..0000000 --- a/src/commands/import/cli_tests.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! CLI parsing tests for import command. -//! -//! Note: Import command has special file existence validation that requires -//! fixtures with temp files, so these tests remain as regular tests. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::{fixture, rstest}; - use std::fs::File; - use std::path::PathBuf; - use tempfile::{tempdir, TempDir}; - - #[fixture] - fn temp_file() -> (TempDir, PathBuf) { - let dir = tempdir().unwrap(); - let path = dir.path().join("test.json"); - File::create(&path).unwrap(); - (dir, path) - } - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - crate::cli_required_arg_test! { - command: "import", - test_name: test_requires_file, - required_arg: "--file", - } - - // ========================================================================= - // Edge case tests (file validation, global --db flag) - // ========================================================================= - - #[rstest] - fn test_file_must_exist() { - let result = - Args::try_parse_from(["code_search", "import", "--file", "nonexistent_file.json"]); - assert!(result.is_err()); - assert!(result.unwrap_err().to_string().contains("File not found")); - } - - #[rstest] - fn test_with_existing_file(temp_file: (TempDir, PathBuf)) { - let (_dir, path) = temp_file; - let result = - Args::try_parse_from(["code_search", "import", "--file", path.to_str().unwrap()]); - assert!(result.is_ok()); - } - - #[rstest] - fn test_db_is_optional(temp_file: (TempDir, PathBuf)) { - let (_dir, path) = temp_file; - let args = - Args::try_parse_from(["code_search", "import", "--file", path.to_str().unwrap()]) - .unwrap(); - assert_eq!(args.db, None); - } - - #[rstest] - fn test_db_can_be_overridden(temp_file: (TempDir, PathBuf)) { - let (_dir, path) = temp_file; - let args = Args::try_parse_from([ - "code_search", - "--db", - "/custom/path.db", - "import", - "--file", - path.to_str().unwrap(), - ]) - .unwrap(); - assert_eq!(args.db, Some(PathBuf::from("/custom/path.db"))); - } -} diff --git a/src/commands/import/execute.rs b/src/commands/import/execute.rs deleted file mode 100644 index 2bfe0dd..0000000 --- a/src/commands/import/execute.rs +++ /dev/null @@ -1,247 +0,0 @@ -use std::error::Error; -use std::fs; - -use cozo::DbInstance; - -use super::ImportCmd; -use crate::commands::Execute; -use crate::queries::import::{clear_project_data, import_graph, ImportError, ImportResult}; -use crate::queries::import_models::CallGraph; - -impl Execute for ImportCmd { - type Output = ImportResult; - - fn execute(self, db: &DbInstance) -> Result> { - // Read and parse call graph - let content = fs::read_to_string(&self.file).map_err(|e| ImportError::FileReadFailed { - path: self.file.display().to_string(), - message: e.to_string(), - })?; - - let graph: CallGraph = - serde_json::from_str(&content).map_err(|e| ImportError::JsonParseFailed { - message: e.to_string(), - })?; - - // Clear existing data if requested - if self.clear { - clear_project_data(db, &self.project)?; - } - - // Import data - let mut result = import_graph(db, &self.project, &graph)?; - result.cleared = self.clear; - - Ok(result) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::db::open_db; - use rstest::{fixture, rstest}; - use std::io::Write; - use tempfile::NamedTempFile; - - fn sample_call_graph_json() -> &'static str { - r#"{ - "structs": { - "MyApp.User": { - "fields": [ - {"default": "nil", "field": "name", "required": true, "inferred_type": "binary()"}, - {"default": "0", "field": "age", "required": false, "inferred_type": "integer()"} - ] - } - }, - "function_locations": { - "MyApp.Accounts": { - "get_user/1:10": { - "name": "get_user", - "arity": 1, - "file": "lib/my_app/accounts.ex", - "column": 7, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15, - "pattern": "id", - "guard": null, - "source_sha": "", - "ast_sha": "" - } - } - }, - "calls": [ - { - "caller": { - "function": "get_user/1", - "line": 12, - "module": "MyApp.Accounts", - "file": "lib/my_app/accounts.ex", - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 2, - "function": "get", - "module": "MyApp.Repo" - } - } - ], - "specs": { - "MyApp.Accounts": [ - { - "arity": 1, - "name": "get_user", - "line": 9, - "kind": "spec", - "clauses": [ - {"full": "@spec get_user(integer()) :: dynamic()", "input_strings": ["integer()"], "return_strings": ["dynamic()"]} - ] - } - ] - } - }"# - } - - fn create_temp_json_file(content: &str) -> NamedTempFile { - let mut file = NamedTempFile::new().expect("Failed to create temp file"); - file.write_all(content.as_bytes()) - .expect("Failed to write temp file"); - file - } - - #[fixture] - fn json_file() -> NamedTempFile { - create_temp_json_file(sample_call_graph_json()) - } - - #[fixture] - fn db_file() -> NamedTempFile { - NamedTempFile::new().expect("Failed to create temp db file") - } - - #[fixture] - fn import_result(json_file: NamedTempFile, db_file: NamedTempFile) -> ImportResult { - let cmd = ImportCmd { - file: json_file.path().to_path_buf(), - project: "test_project".to_string(), - clear: false, - }; - let db = open_db(db_file.path()).expect("Failed to open db"); - cmd.execute(&db).expect("Import should succeed") - } - - #[rstest] - fn test_import_creates_schemas(import_result: ImportResult) { - assert!(!import_result.schemas.created.is_empty() || !import_result.schemas.already_existed.is_empty()); - } - - #[rstest] - fn test_import_modules(import_result: ImportResult) { - assert_eq!(import_result.modules_imported, 2); // MyApp.Accounts + MyApp.User (from structs) - } - - #[rstest] - fn test_import_functions(import_result: ImportResult) { - assert_eq!(import_result.functions_imported, 1); // get_user/1 - } - - #[rstest] - fn test_import_calls(import_result: ImportResult) { - assert_eq!(import_result.calls_imported, 1); - } - - #[rstest] - fn test_import_structs(import_result: ImportResult) { - assert_eq!(import_result.structs_imported, 2); // 2 fields in MyApp.User - } - - #[rstest] - fn test_import_function_locations(import_result: ImportResult) { - assert_eq!(import_result.function_locations_imported, 1); - } - - #[rstest] - fn test_import_with_clear_flag(json_file: NamedTempFile, db_file: NamedTempFile) { - // First import - let cmd1 = ImportCmd { - file: json_file.path().to_path_buf(), - project: "test_project".to_string(), - clear: false, - }; - let db = open_db(db_file.path()).expect("Failed to open db"); - cmd1.execute(&db) - .expect("First import should succeed"); - - // Second import with clear - let cmd2 = ImportCmd { - file: json_file.path().to_path_buf(), - project: "test_project".to_string(), - clear: true, - }; - let result = cmd2 - .execute(&db) - .expect("Second import should succeed"); - - assert!(result.cleared); - assert_eq!(result.modules_imported, 2); - } - - #[rstest] - fn test_import_empty_graph(db_file: NamedTempFile) { - let empty_json = r#"{ - "structs": {}, - "function_locations": {}, - "calls": [], - "type_signatures": {} - }"#; - - let json_file = create_temp_json_file(empty_json); - - let cmd = ImportCmd { - file: json_file.path().to_path_buf(), - project: "test_project".to_string(), - clear: false, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db).expect("Import should succeed"); - - assert_eq!(result.modules_imported, 0); - assert_eq!(result.functions_imported, 0); - assert_eq!(result.calls_imported, 0); - assert_eq!(result.structs_imported, 0); - assert_eq!(result.function_locations_imported, 0); - } - - #[rstest] - fn test_import_invalid_json_fails(db_file: NamedTempFile) { - let invalid_json = "{ not valid json }"; - let json_file = create_temp_json_file(invalid_json); - - let cmd = ImportCmd { - file: json_file.path().to_path_buf(), - project: "test_project".to_string(), - clear: false, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db); - assert!(result.is_err()); - } - - #[rstest] - fn test_import_nonexistent_file_fails(db_file: NamedTempFile) { - let cmd = ImportCmd { - file: "/nonexistent/path/call_graph.json".into(), - project: "test_project".to_string(), - clear: false, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db); - assert!(result.is_err()); - } -} diff --git a/src/commands/import/mod.rs b/src/commands/import/mod.rs deleted file mode 100644 index 75d43c6..0000000 --- a/src/commands/import/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -mod cli_tests; -mod execute; -mod output; -mod output_tests; - -use std::error::Error; -use std::path::PathBuf; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, Execute}; -use crate::output::{OutputFormat, Outputable}; - -const DEFAULT_PROJECT: &str = "default"; - -fn validate_file_exists(s: &str) -> Result { - let path = PathBuf::from(s); - if path.exists() { - Ok(path) - } else { - Err(format!("File not found: {}", path.display())) - } -} - -/// Import a call graph JSON file into the database -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search import -f call_graph.json # Import with default project name - code_search import -f cg.json -p my_app # Import into 'my_app' project - code_search import -f cg.json --clear # Clear DB before importing")] -pub struct ImportCmd { - /// Path to the call graph JSON file - #[arg(short, long, value_parser = validate_file_exists)] - pub file: PathBuf, - /// Project name for namespacing (allows multiple projects in same DB) - #[arg(short, long, default_value = DEFAULT_PROJECT)] - pub project: String, - /// Clear all existing data before import (or just project data if --project is set) - #[arg(long, default_value_t = false)] - pub clear: bool, -} - -impl CommandRunner for ImportCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/import/output.rs b/src/commands/import/output.rs deleted file mode 100644 index 1ab6ed4..0000000 --- a/src/commands/import/output.rs +++ /dev/null @@ -1,32 +0,0 @@ -//! Output formatting for import command results. - -use crate::output::Outputable; -use crate::queries::import::ImportResult; - -impl Outputable for ImportResult { - fn to_table(&self) -> String { - let mut output = String::new(); - - if self.cleared { - output.push_str("Cleared existing project data.\n\n"); - } - - output.push_str("Import Summary:\n"); - output.push_str(&format!(" Modules: {}\n", self.modules_imported)); - output.push_str(&format!(" Functions: {}\n", self.functions_imported)); - output.push_str(&format!(" Calls: {}\n", self.calls_imported)); - output.push_str(&format!(" Structs: {}\n", self.structs_imported)); - output.push_str(&format!(" Locations: {}\n", self.function_locations_imported)); - output.push_str(&format!(" Specs: {}\n", self.specs_imported)); - output.push_str(&format!(" Types: {}\n", self.types_imported)); - - if !self.schemas.created.is_empty() { - output.push_str("\nCreated Schemas:\n"); - for schema in &self.schemas.created { - output.push_str(&format!(" - {}\n", schema)); - } - } - - output - } -} diff --git a/src/commands/import/output_tests.rs b/src/commands/import/output_tests.rs deleted file mode 100644 index f40f0db..0000000 --- a/src/commands/import/output_tests.rs +++ /dev/null @@ -1,119 +0,0 @@ -//! Output formatting tests for import command. - -#[cfg(test)] -mod tests { - use crate::output::OutputFormat; - use crate::queries::import::{ImportResult, SchemaResult}; - use rstest::{fixture, rstest}; - - const EMPTY_TABLE_OUTPUT: &str = "\ -Import Summary: - Modules: 0 - Functions: 0 - Calls: 0 - Structs: 0 - Locations: 0 - Specs: 0 - Types: 0 -"; - - const FULL_TABLE_OUTPUT: &str = "\ -Cleared existing project data. - -Import Summary: - Modules: 10 - Functions: 50 - Calls: 100 - Structs: 5 - Locations: 45 - Specs: 25 - Types: 12 - -Created Schemas: - - modules - - functions -"; - - const FULL_TABLE_OUTPUT_NO_CLEAR: &str = "\ -Import Summary: - Modules: 10 - Functions: 50 - Calls: 100 - Structs: 5 - Locations: 45 - Specs: 25 - Types: 12 - -Created Schemas: - - modules - - functions -"; - - - #[fixture] - fn empty_result() -> ImportResult { - ImportResult::default() - } - - #[fixture] - fn full_result() -> ImportResult { - ImportResult { - schemas: SchemaResult { - created: vec!["modules".to_string(), "functions".to_string()], - already_existed: vec!["calls".to_string()], - }, - cleared: true, - modules_imported: 10, - functions_imported: 50, - calls_imported: 100, - structs_imported: 5, - function_locations_imported: 45, - specs_imported: 25, - types_imported: 12, - } - } - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ImportResult, - expected: EMPTY_TABLE_OUTPUT, - } - - crate::output_table_test! { - test_name: test_to_table_with_data, - fixture: full_result, - fixture_type: ImportResult, - expected: FULL_TABLE_OUTPUT, - } - - #[rstest] - fn test_to_table_no_clear(full_result: ImportResult) { - use crate::output::Outputable; - let mut result = full_result; - result.cleared = false; - assert_eq!(result.to_table(), FULL_TABLE_OUTPUT_NO_CLEAR); - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: full_result, - fixture_type: ImportResult, - expected: crate::test_utils::load_output_fixture("import", "full.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: full_result, - fixture_type: ImportResult, - expected: crate::test_utils::load_output_fixture("import", "full.toon"), - format: Toon, - } - - #[rstest] - fn test_format_table_delegates_to_to_table(full_result: ImportResult) { - use crate::output::Outputable; - assert_eq!(full_result.format(OutputFormat::Table), FULL_TABLE_OUTPUT); - } -} diff --git a/src/commands/large_functions/execute.rs b/src/commands/large_functions/execute.rs deleted file mode 100644 index 576fcfd..0000000 --- a/src/commands/large_functions/execute.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; - -use serde::Serialize; - -use super::LargeFunctionsCmd; -use crate::commands::Execute; -use crate::queries::large_functions::find_large_functions; -use crate::types::{ModuleCollectionResult, ModuleGroup}; - -/// A single large function entry -#[derive(Debug, Clone, Serialize)] -pub struct LargeFunctionEntry { - pub name: String, - pub arity: i64, - pub start_line: i64, - pub end_line: i64, - pub lines: i64, - pub file: String, -} - -impl Execute for LargeFunctionsCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let large_functions = find_large_functions( - db, - self.min_lines, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.include_generated, - self.common.limit, - )?; - - let total_items = large_functions.len(); - - // Group by module while preserving sort order (largest functions first) - // Track module order separately to maintain insertion order - let mut module_order: Vec = Vec::new(); - let mut module_map: HashMap)> = HashMap::new(); - - for func in large_functions { - let entry = LargeFunctionEntry { - name: func.name, - arity: func.arity, - start_line: func.start_line, - end_line: func.end_line, - lines: func.lines, - file: func.file.clone(), - }; - - if !module_map.contains_key(&func.module) { - module_order.push(func.module.clone()); - } - - module_map - .entry(func.module) - .or_insert_with(|| (func.file, Vec::new())) - .1 - .push(entry); - } - - let items: Vec> = module_order - .into_iter() - .filter_map(|name| { - module_map.remove(&name).map(|(file, entries)| ModuleGroup { - name, - file, - entries, - function_count: None, - }) - }) - .collect(); - - Ok(ModuleCollectionResult { - module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items, - items, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_large_functions_cmd_structure() { - let cmd = LargeFunctionsCmd { - min_lines: 100, - include_generated: false, - module: Some("MyApp".to_string()), - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 20, - }, - }; - - assert_eq!(cmd.min_lines, 100); - assert!(!cmd.include_generated); - assert_eq!(cmd.module, Some("MyApp".to_string())); - } -} diff --git a/src/commands/large_functions/mod.rs b/src/commands/large_functions/mod.rs deleted file mode 100644 index 245fead..0000000 --- a/src/commands/large_functions/mod.rs +++ /dev/null @@ -1,46 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find large functions that may need refactoring -/// -/// Large functions are those with many lines of code (large `end_line - start_line`). -/// These typically indicate functions that should be broken down into smaller pieces. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search large-functions # Find functions with 50+ lines - code_search large-functions MyApp.Web # Filter to MyApp.Web namespace - code_search large-functions --min-lines 100 # Find functions with 100+ lines - code_search large-functions --include-generated # Include macro-generated functions - code_search large-functions -l 20 # Show top 20 largest functions -")] -pub struct LargeFunctionsCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Minimum lines to be considered large - #[arg(long, default_value = "50")] - pub min_lines: i64, - - /// Include macro-generated functions (excluded by default) - #[arg(long)] - pub include_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for LargeFunctionsCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/large_functions/output.rs b/src/commands/large_functions/output.rs deleted file mode 100644 index f133de2..0000000 --- a/src/commands/large_functions/output.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Output formatting for large functions command results. - -use super::execute::LargeFunctionEntry; -use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; - -impl TableFormatter for ModuleCollectionResult { - type Entry = LargeFunctionEntry; - - fn format_header(&self) -> String { - "Large Functions".to_string() - } - - fn format_empty_message(&self) -> String { - "No large functions found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} large function(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, entry: &LargeFunctionEntry, _module: &str, _file: &str) -> String { - format!( - "{}/{} ({} lines) - {}:{}-{}", - entry.name, entry.arity, entry.lines, entry.file, entry.start_line, entry.end_line - ) - } - - fn blank_before_module(&self) -> bool { - true - } - - fn blank_after_summary(&self) -> bool { - false - } -} diff --git a/src/commands/location/cli_tests.rs b/src/commands/location/cli_tests.rs deleted file mode 100644 index b3b0dfc..0000000 --- a/src/commands/location/cli_tests.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! CLI parsing tests for location command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "location", - test_name: test_requires_function, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_function_only, - args: ["get_user"], - field: function, - expected: "get_user", - } - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_module, - args: ["get_user", "MyApp.Accounts"], - field: module, - expected: Some("MyApp.Accounts".to_string()), - } - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_arity, - args: ["get_user", "MyApp.Accounts", "--arity", "1"], - field: arity, - expected: Some(1), - } - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_regex, - args: ["get_.*", "MyApp.*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_project, - args: ["get_user", "MyApp.Accounts", "--project", "my_app"], - field: common.project, - expected: "my_app", - } - - crate::cli_option_test! { - command: "location", - variant: Location, - test_name: test_with_limit, - args: ["get_user", "--limit", "10"], - field: common.limit, - expected: 10, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "location", - variant: Location, - required_args: ["get_user"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/location/execute.rs b/src/commands/location/execute.rs deleted file mode 100644 index fd1c6d6..0000000 --- a/src/commands/location/execute.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; - -use serde::Serialize; - -use super::LocationCmd; -use crate::commands::Execute; -use crate::queries::location::{find_locations, FunctionLocation}; - -/// A single clause (definition) of a function -#[derive(Debug, Clone, Serialize)] -pub struct LocationClause { - pub line: i64, - pub start_line: i64, - pub end_line: i64, - #[serde(skip_serializing_if = "String::is_empty")] - pub pattern: String, - #[serde(skip_serializing_if = "String::is_empty")] - pub guard: String, -} - -/// A function with all its clauses grouped together -#[derive(Debug, Clone, Serialize)] -pub struct LocationFunction { - pub name: String, - pub arity: i64, - pub kind: String, - pub file: String, - pub clauses: Vec, -} - -/// A module containing functions -#[derive(Debug, Clone, Serialize)] -pub struct LocationModule { - pub name: String, - pub functions: Vec, -} - -/// Result of the location command execution -#[derive(Debug, Default, Serialize)] -pub struct LocationResult { - pub module_pattern: String, - pub function_pattern: String, - pub total_clauses: usize, - pub modules: Vec, -} - -impl LocationResult { - /// Build grouped result from flat FunctionLocation list - fn from_locations( - module_pattern: String, - function_pattern: String, - locations: Vec, - ) -> Self { - let total_clauses = locations.len(); - - // Group by module, then by (function_name, arity) - // Use BTreeMap for consistent ordering - let mut module_map: BTreeMap)>> = - BTreeMap::new(); - - for loc in locations { - let func_key = (loc.name.clone(), loc.arity); - let clause = LocationClause { - line: loc.line, - start_line: loc.start_line, - end_line: loc.end_line, - pattern: loc.pattern, - guard: loc.guard, - }; - - module_map - .entry(loc.module.clone()) - .or_default() - .entry(func_key) - .or_insert_with(|| (loc.kind.clone(), loc.file.clone(), Vec::new())) - .2 - .push(clause); - } - - // Convert to final structure - let modules: Vec = module_map - .into_iter() - .map(|(module_name, funcs)| { - let functions: Vec = funcs - .into_iter() - .map(|((name, arity), (kind, file, clauses))| LocationFunction { - name, - arity, - kind, - file, - clauses, - }) - .collect(); - LocationModule { - name: module_name, - functions, - } - }) - .collect(); - - LocationResult { - module_pattern, - function_pattern, - total_clauses, - modules, - } - } -} - -impl Execute for LocationCmd { - type Output = LocationResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let locations = find_locations( - db, - self.module.as_deref(), - &self.function, - self.arity, - &self.common.project, - self.common.regex, - self.common.limit, - )?; - - Ok(LocationResult::from_locations( - self.module.unwrap_or_default(), - self.function, - locations, - )) - } -} diff --git a/src/commands/location/execute_tests.rs b/src/commands/location/execute_tests.rs deleted file mode 100644 index a195c30..0000000 --- a/src/commands/location/execute_tests.rs +++ /dev/null @@ -1,320 +0,0 @@ -//! Execute tests for location command. - -#[cfg(test)] -mod tests { - use super::super::LocationCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - crate::execute_test! { - test_name: test_location_exact_match, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp.Accounts".to_string()), - function: "get_user".to_string(), - arity: Some(1), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.modules.len(), 1); - assert_eq!(result.modules[0].functions.len(), 1); - let func = &result.modules[0].functions[0]; - assert_eq!(func.file, "lib/my_app/accounts.ex"); - assert_eq!(func.clauses[0].start_line, 10); - assert_eq!(func.clauses[0].end_line, 15); - }, - } - - // get_user exists in Accounts with arities 1 and 2 - crate::execute_test! { - test_name: test_location_without_module, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - // 2 functions (get_user/1 and get_user/2) in 1 module - assert_eq!(result.total_clauses, 2); - assert_eq!(result.modules.len(), 1); - assert_eq!(result.modules[0].name, "MyApp.Accounts"); - assert_eq!(result.modules[0].functions.len(), 2); - }, - } - - // Functions with "user" in name: get_user/1, get_user/2, list_users = 3 - crate::execute_test! { - test_name: test_location_without_module_multiple_matches, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: ".*user.*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 3); - }, - } - - // get_user has two arities in Accounts - crate::execute_test! { - test_name: test_location_without_arity, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp.Accounts".to_string()), - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 2); - }, - } - - crate::execute_test! { - test_name: test_location_with_regex, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp\\..*".to_string()), - function: ".*user.*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 3); - }, - } - - crate::execute_test! { - test_name: test_location_format, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp.Accounts".to_string()), - function: "get_user".to_string(), - arity: Some(1), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - let func = &result.modules[0].functions[0]; - assert_eq!( - format!("{}:{}:{}", func.file, func.clauses[0].start_line, func.clauses[0].end_line), - "lib/my_app/accounts.ex:10:15" - ); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_location_no_match, - fixture: populated_db, - cmd: LocationCmd { - module: Some("NonExistent".to_string()), - function: "foo".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: modules, - } - - crate::execute_no_match_test! { - test_name: test_location_nonexistent_project, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "nonexistent_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: modules, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_location_with_project_filter, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp.Accounts".to_string()), - function: "get_user".to_string(), - arity: Some(1), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.modules.len(), 1); - assert_eq!(result.modules[0].functions.len(), 1); - }, - } - - // 6 functions with arity 1: get_user/1, validate_email, process, fetch, all, notify - crate::execute_test! { - test_name: test_location_arity_filter_without_module, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: ".*".to_string(), - arity: Some(1), - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - let total_funcs: usize = result.modules.iter().map(|m| m.functions.len()).sum(); - assert_eq!(total_funcs, 6); - // All functions should have arity 1 - for module in &result.modules { - for func in &module.functions { - assert_eq!(func.arity, 1); - } - } - }, - } - - crate::execute_test! { - test_name: test_location_project_filter_without_module, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: "get_user".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 2); - }, - } - - // Accounts has get_user/1, get_user/2, list_users matching ".*user.*" = 3 - crate::execute_test! { - test_name: test_location_function_regex_with_exact_module, - fixture: populated_db, - cmd: LocationCmd { - module: Some("MyApp.Accounts".to_string()), - function: ".*user.*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 3); - }, - } - - crate::execute_test! { - test_name: test_location_arity_zero, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: "list_users".to_string(), - arity: Some(0), - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_clauses, 1); - assert_eq!(result.modules[0].functions[0].arity, 0); - }, - } - - crate::execute_test! { - test_name: test_location_with_limit, - fixture: populated_db, - cmd: LocationCmd { - module: None, - function: ".*user.*".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 1, - }, - }, - assertions: |result| { - // Limit applies to raw results before grouping - assert_eq!(result.total_clauses, 1); - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: LocationCmd, - cmd: LocationCmd { - module: Some("MyApp".to_string()), - function: "foo".to_string(), - arity: None, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/location/mod.rs b/src/commands/location/mod.rs deleted file mode 100644 index b4b016e..0000000 --- a/src/commands/location/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find where a function is defined (file:line_start:line_end) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search location get_user # Find all get_user functions - code_search location get_user MyApp # In specific module - code_search location get_user -a 1 # With specific arity - code_search location -r 'get_.*' # Regex pattern matching -")] -pub struct LocationCmd { - /// Function name (exact match or pattern with --regex) - pub function: String, - - /// Module name (exact match or pattern with --regex). If not specified, searches all modules. - pub module: Option, - - /// Function arity (optional, matches all arities if not specified) - #[arg(short, long)] - pub arity: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for LocationCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/location/output.rs b/src/commands/location/output.rs deleted file mode 100644 index 7a6a80f..0000000 --- a/src/commands/location/output.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Output formatting for location command results. - -use crate::output::Outputable; -use super::execute::LocationResult; - -impl Outputable for LocationResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - lines.push(format!("Location: {}.{}", self.module_pattern, self.function_pattern)); - lines.push(String::new()); - - if !self.modules.is_empty() { - let func_count: usize = self.modules.iter().map(|m| m.functions.len()).sum(); - lines.push(format!( - "Found {} clause(s) in {} function(s) across {} module(s):", - self.total_clauses, - func_count, - self.modules.len() - )); - lines.push(String::new()); - - for module in &self.modules { - lines.push(format!("{}:", module.name)); - for func in &module.functions { - lines.push(format!( - " {}/{} [{}] ({})", - func.name, func.arity, func.kind, func.file - )); - for clause in &func.clauses { - let pattern_str = if clause.pattern.is_empty() { - String::new() - } else { - format!(" ({})", clause.pattern) - }; - let guard_str = if clause.guard.is_empty() { - String::new() - } else { - format!(" when {}", clause.guard) - }; - lines.push(format!( - " L{}:{}{}{}", - clause.start_line, clause.end_line, pattern_str, guard_str - )); - } - } - } - } else { - lines.push("No locations found.".to_string()); - } - - lines.join("\n") - } -} diff --git a/src/commands/location/output_tests.rs b/src/commands/location/output_tests.rs deleted file mode 100644 index 2c7f752..0000000 --- a/src/commands/location/output_tests.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! Output formatting tests for location command. - -#[cfg(test)] -mod tests { - use super::super::execute::{LocationClause, LocationFunction, LocationModule, LocationResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Location: MyApp.foo - -No locations found."; - - const SINGLE_TABLE: &str = "\ -Location: MyApp.Accounts.get_user - -Found 1 clause(s) in 1 function(s) across 1 module(s): - -MyApp.Accounts: - get_user/1 [def] (lib/my_app/accounts.ex) - L10:15"; - - const MULTIPLE_TABLE: &str = "\ -Location: MyApp.*.user - -Found 2 clause(s) in 2 function(s) across 2 module(s): - -MyApp.Accounts: - get_user/1 [def] (lib/my_app/accounts.ex) - L10:15 -MyApp.Users: - create_user/1 [def] (lib/my_app/users.ex) - L5:12"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> LocationResult { - LocationResult { - module_pattern: "MyApp".to_string(), - function_pattern: "foo".to_string(), - total_clauses: 0, - modules: vec![], - } - } - - #[fixture] - fn single_result() -> LocationResult { - LocationResult { - module_pattern: "MyApp.Accounts".to_string(), - function_pattern: "get_user".to_string(), - total_clauses: 1, - modules: vec![LocationModule { - name: "MyApp.Accounts".to_string(), - functions: vec![LocationFunction { - name: "get_user".to_string(), - arity: 1, - kind: "def".to_string(), - file: "lib/my_app/accounts.ex".to_string(), - clauses: vec![LocationClause { - line: 10, - start_line: 10, - end_line: 15, - pattern: String::new(), - guard: String::new(), - }], - }], - }], - } - } - - #[fixture] - fn multiple_result() -> LocationResult { - LocationResult { - module_pattern: "MyApp.*".to_string(), - function_pattern: "user".to_string(), - total_clauses: 2, - modules: vec![ - LocationModule { - name: "MyApp.Accounts".to_string(), - functions: vec![LocationFunction { - name: "get_user".to_string(), - arity: 1, - kind: "def".to_string(), - file: "lib/my_app/accounts.ex".to_string(), - clauses: vec![LocationClause { - line: 10, - start_line: 10, - end_line: 15, - pattern: String::new(), - guard: String::new(), - }], - }], - }, - LocationModule { - name: "MyApp.Users".to_string(), - functions: vec![LocationFunction { - name: "create_user".to_string(), - arity: 1, - kind: "def".to_string(), - file: "lib/my_app/users.ex".to_string(), - clauses: vec![LocationClause { - line: 5, - start_line: 5, - end_line: 12, - pattern: String::new(), - guard: String::new(), - }], - }], - }, - ], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: LocationResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: LocationResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_multiple, - fixture: multiple_result, - fixture_type: LocationResult, - expected: MULTIPLE_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: LocationResult, - expected: crate::test_utils::load_output_fixture("location", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/many_clauses/execute.rs b/src/commands/many_clauses/execute.rs deleted file mode 100644 index 32d8757..0000000 --- a/src/commands/many_clauses/execute.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; - -use serde::Serialize; - -use super::ManyClausesCmd; -use crate::commands::Execute; -use crate::queries::many_clauses::find_many_clauses; -use crate::types::{ModuleCollectionResult, ModuleGroup}; - -/// A single function with many clauses entry -#[derive(Debug, Clone, Serialize)] -pub struct ManyClausesEntry { - pub name: String, - pub arity: i64, - pub clauses: i64, - pub first_line: i64, - pub last_line: i64, - pub file: String, -} - -impl Execute for ManyClausesCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let many_clauses = find_many_clauses( - db, - self.min_clauses, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.include_generated, - self.common.limit, - )?; - - let total_items = many_clauses.len(); - - // Group by module while preserving sort order (most clauses first) - let mut module_order: Vec = Vec::new(); - let mut module_map: HashMap)> = HashMap::new(); - - for func in many_clauses { - let entry = ManyClausesEntry { - name: func.name, - arity: func.arity, - clauses: func.clauses, - first_line: func.first_line, - last_line: func.last_line, - file: func.file.clone(), - }; - - if !module_map.contains_key(&func.module) { - module_order.push(func.module.clone()); - } - - module_map - .entry(func.module) - .or_insert_with(|| (func.file, Vec::new())) - .1 - .push(entry); - } - - let items: Vec> = module_order - .into_iter() - .filter_map(|name| { - module_map.remove(&name).map(|(file, entries)| ModuleGroup { - name, - file, - entries, - function_count: None, - }) - }) - .collect(); - - Ok(ModuleCollectionResult { - module_pattern: self.module.clone().unwrap_or_else(|| "*".to_string()), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items, - items, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_many_clauses_cmd_structure() { - let cmd = ManyClausesCmd { - min_clauses: 10, - include_generated: false, - module: Some("MyApp".to_string()), - common: crate::commands::CommonArgs { - project: "default".to_string(), - regex: false, - limit: 20, - }, - }; - - assert_eq!(cmd.min_clauses, 10); - assert!(!cmd.include_generated); - assert_eq!(cmd.module, Some("MyApp".to_string())); - } -} diff --git a/src/commands/many_clauses/mod.rs b/src/commands/many_clauses/mod.rs deleted file mode 100644 index 3195bc2..0000000 --- a/src/commands/many_clauses/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions with many pattern-matched heads -/// -/// Functions with many clauses are those with multiple pattern-matched definitions, -/// indicating high branching complexity. These typically indicate functions that -/// should be broken down or simplified. -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search many-clauses # Find functions with 5+ clauses - code_search many-clauses MyApp.Web # Filter to MyApp.Web namespace - code_search many-clauses --min-clauses 10 # Find functions with 10+ clauses - code_search many-clauses --include-generated # Include macro-generated functions - code_search many-clauses -l 20 # Show top 20 functions with most clauses -")] -pub struct ManyClausesCmd { - /// Module filter pattern (substring match by default, regex with --regex) - pub module: Option, - - /// Minimum clauses to be considered - #[arg(long, default_value = "5")] - pub min_clauses: i64, - - /// Include macro-generated functions (excluded by default) - #[arg(long)] - pub include_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for ManyClausesCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/many_clauses/output.rs b/src/commands/many_clauses/output.rs deleted file mode 100644 index 32b9a33..0000000 --- a/src/commands/many_clauses/output.rs +++ /dev/null @@ -1,40 +0,0 @@ -//! Output formatting for many clauses command results. - -use super::execute::ManyClausesEntry; -use crate::output::TableFormatter; -use crate::types::ModuleCollectionResult; - -impl TableFormatter for ModuleCollectionResult { - type Entry = ManyClausesEntry; - - fn format_header(&self) -> String { - "Functions with Many Clauses".to_string() - } - - fn format_empty_message(&self) -> String { - "No functions with many clauses found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} function(s) with many clauses in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, entry: &ManyClausesEntry, _module: &str, _file: &str) -> String { - format!( - "{}/{} ({} clauses) - {}:{}-{}", - entry.name, entry.arity, entry.clauses, entry.file, entry.first_line, entry.last_line - ) - } - - fn blank_before_module(&self) -> bool { - true - } - - fn blank_after_summary(&self) -> bool { - false - } -} diff --git a/src/commands/mod.rs b/src/commands/mod.rs deleted file mode 100644 index eac19b7..0000000 --- a/src/commands/mod.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! Command definitions and implementations. -//! -//! Each command is defined in its own module with: -//! - The command struct with clap attributes for CLI parsing -//! - Common arguments shared via [`CommonArgs`] - -use clap::Args; - -/// Common arguments shared across most commands. -/// -/// Use `#[command(flatten)]` to include these in a command struct: -/// ```ignore -/// pub struct MyCmd { -/// pub module: String, -/// #[command(flatten)] -/// pub common: CommonArgs, -/// } -/// ``` -#[derive(Args, Debug, Clone)] -pub struct CommonArgs { - /// Project to search in - #[arg(long, default_value = "default")] - pub project: String, - - /// Treat patterns as regular expressions - #[arg(short, long, default_value_t = false)] - pub regex: bool, - - /// Maximum number of results to return (1-1000) - #[arg(short, long, default_value_t = 100, value_parser = clap::value_parser!(u32).range(1..=1000))] - pub limit: u32, -} - -mod accepts; -mod boundaries; -mod browse_module; -mod calls_from; -mod calls_to; -mod clusters; -mod complexity; -mod cycles; -mod depended_by; -mod depends_on; -mod describe; -mod duplicates; -mod function; -mod god_modules; -mod hotspots; -pub mod import; -mod large_functions; -mod location; -mod many_clauses; -mod path; -mod returns; -mod reverse_trace; -mod search; -pub mod setup; -mod struct_usage; -mod trace; -mod unused; - -pub use accepts::AcceptsCmd; -pub use boundaries::BoundariesCmd; -pub use browse_module::BrowseModuleCmd; -pub use calls_from::CallsFromCmd; -pub use calls_to::CallsToCmd; -pub use clusters::ClustersCmd; -pub use complexity::ComplexityCmd; -pub use cycles::CyclesCmd; -pub use depended_by::DependedByCmd; -pub use depends_on::DependsOnCmd; -pub use describe::DescribeCmd; -pub use duplicates::DuplicatesCmd; -pub use function::FunctionCmd; -pub use god_modules::GodModulesCmd; -pub use hotspots::HotspotsCmd; -pub use import::ImportCmd; -pub use large_functions::LargeFunctionsCmd; -pub use location::LocationCmd; -pub use many_clauses::ManyClausesCmd; -pub use path::PathCmd; -pub use returns::ReturnsCmd; -pub use reverse_trace::ReverseTraceCmd; -pub use search::SearchCmd; -pub use setup::SetupCmd; -pub use struct_usage::StructUsageCmd; -pub use trace::TraceCmd; -pub use unused::UnusedCmd; - -use clap::Subcommand; -use enum_dispatch::enum_dispatch; -use std::error::Error; - -use cozo::DbInstance; - -use crate::output::{OutputFormat, Outputable}; - -/// Trait for executing commands with command-specific result types. -pub trait Execute { - type Output: Outputable; - - fn execute(self, db: &DbInstance) -> Result>; -} - -/// Trait for commands that can be executed and formatted. -/// Auto-implemented for all Command variants via enum_dispatch. -#[enum_dispatch] -pub trait CommandRunner { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result>; -} - -#[derive(Subcommand, Debug)] -#[enum_dispatch(CommandRunner)] -pub enum Command { - /// Create database schema without importing data - Setup(SetupCmd), - - /// Import a call graph JSON file into the database - Import(ImportCmd), - - /// Browse all definitions in a module or file - BrowseModule(BrowseModuleCmd), - - /// Search for modules or functions by name pattern - Search(SearchCmd), - - /// Find where a function is defined (file:line_start:line_end) - Location(LocationCmd), - - /// Show what a module/function calls (outgoing edges) - CallsFrom(CallsFromCmd), - - /// Show what calls a module/function (incoming edges) - CallsTo(CallsToCmd), - - /// Analyze module connectivity using namespace-based clustering - Clusters(ClustersCmd), - - /// Display complexity metrics for functions - Complexity(ComplexityCmd), - - /// Detect circular dependencies between modules - Cycles(CyclesCmd), - - /// Display detailed documentation about available commands - Describe(DescribeCmd), - - /// Show function signature (args, return type) - Function(FunctionCmd), - - /// Trace call chains from a starting function (forward traversal) - Trace(TraceCmd), - - /// Trace call chains backwards - who calls the callers of a target - ReverseTrace(ReverseTraceCmd), - - /// Find a call path between two functions - Path(PathCmd), - - /// Find functions accepting a specific type pattern - Accepts(AcceptsCmd), - - /// Find functions returning a specific type pattern - Returns(ReturnsCmd), - - /// Find functions that accept or return a specific type pattern - StructUsage(StructUsageCmd), - - /// Show what modules a given module depends on (outgoing module dependencies) - DependsOn(DependsOnCmd), - - /// Show what modules depend on a given module (incoming module dependencies) - DependedBy(DependedByCmd), - - /// Find functions that are never called - Unused(UnusedCmd), - - /// Find functions with identical or near-identical implementations - Duplicates(DuplicatesCmd), - - /// Find functions with the most incoming/outgoing calls - Hotspots(HotspotsCmd), - - /// Find boundary modules - modules with high fan-in but low fan-out - Boundaries(BoundariesCmd), - - /// Find god modules - modules with high function count and high connectivity - GodModules(GodModulesCmd), - - /// Find large functions that may need refactoring - LargeFunctions(LargeFunctionsCmd), - - /// Find functions with many pattern-matched heads - ManyClauses(ManyClausesCmd), - - /// Catch-all for unknown commands - #[command(external_subcommand)] - Unknown(Vec), -} - -// CommandRunner implementations are provided by each command's module. -// The enum_dispatch macro automatically generates dispatch logic for the Command enum. - -// Special handling for Unknown variant - not a real command -impl CommandRunner for Vec { - fn run(self, _db: &DbInstance, _format: OutputFormat) -> Result> { - Err(format!("Unknown command: {}", self.first().unwrap_or(&String::new())).into()) - } -} diff --git a/src/commands/path/cli_tests.rs b/src/commands/path/cli_tests.rs deleted file mode 100644 index 2ae388b..0000000 --- a/src/commands/path/cli_tests.rs +++ /dev/null @@ -1,187 +0,0 @@ -//! CLI parsing tests for path command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - // Path command has many required args, so we test them as edge cases below - - crate::cli_option_test! { - command: "path", - variant: Path, - test_name: test_with_limit, - args: [ - "--from-module", "MyApp", - "--from-function", "foo", - "--to-module", "MyApp", - "--to-function", "bar", - "--limit", "5" - ], - field: limit, - expected: 5, - } - - crate::cli_option_test! { - command: "path", - variant: Path, - test_name: test_with_depth, - args: [ - "--from-module", "MyApp", - "--from-function", "foo", - "--to-module", "MyApp", - "--to-function", "bar", - "--depth", "15" - ], - field: depth, - expected: 15, - } - - crate::cli_option_test! { - command: "path", - variant: Path, - test_name: test_with_arities, - args: [ - "--from-module", "MyApp.Controller", - "--from-function", "index", - "--from-arity", "2", - "--to-module", "MyApp.Repo", - "--to-function", "get", - "--to-arity", "2" - ], - field: from_arity, - expected: Some(2), - } - - // ========================================================================= - // Edge case tests (multiple required args, depth validation) - // ========================================================================= - - #[rstest] - fn test_requires_all_args() { - let result = Args::try_parse_from(["code_search", "path"]); - assert!(result.is_err()); - } - - #[rstest] - fn test_requires_to_args() { - let result = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp.Controller", - "--from-function", - "index", - ]); - assert!(result.is_err()); - } - - #[rstest] - fn test_with_all_required_args() { - let args = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp.Controller", - "--from-function", - "index", - "--to-module", - "MyApp.Repo", - "--to-function", - "get", - ]) - .unwrap(); - match args.command { - crate::commands::Command::Path(cmd) => { - assert_eq!(cmd.from_module, "MyApp.Controller"); - assert_eq!(cmd.from_function, "index"); - assert_eq!(cmd.to_module, "MyApp.Repo"); - assert_eq!(cmd.to_function, "get"); - assert_eq!(cmd.depth, 10); // default - assert_eq!(cmd.limit, 100); // default - } - _ => panic!("Expected Path command"), - } - } - - #[rstest] - fn test_depth_zero_rejected() { - let result = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp", - "--from-function", - "foo", - "--to-module", - "MyApp", - "--to-function", - "bar", - "--depth", - "0", - ]); - assert!(result.is_err()); - } - - #[rstest] - fn test_depth_exceeds_max_rejected() { - let result = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp", - "--from-function", - "foo", - "--to-module", - "MyApp", - "--to-function", - "bar", - "--depth", - "21", - ]); - assert!(result.is_err()); - } - - #[rstest] - fn test_limit_zero_rejected() { - let result = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp", - "--from-function", - "foo", - "--to-module", - "MyApp", - "--to-function", - "bar", - "--limit", - "0", - ]); - assert!(result.is_err()); - } - - #[rstest] - fn test_limit_exceeds_max_rejected() { - let result = Args::try_parse_from([ - "code_search", - "path", - "--from-module", - "MyApp", - "--from-function", - "foo", - "--to-module", - "MyApp", - "--to-function", - "bar", - "--limit", - "1001", - ]); - assert!(result.is_err()); - } -} diff --git a/src/commands/path/execute.rs b/src/commands/path/execute.rs deleted file mode 100644 index 2dee335..0000000 --- a/src/commands/path/execute.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::PathCmd; -use crate::commands::Execute; -use crate::queries::path::{find_paths, CallPath}; - -/// Result of the path command execution -#[derive(Debug, Default, Serialize)] -pub struct PathResult { - pub from_module: String, - pub from_function: String, - pub to_module: String, - pub to_function: String, - pub max_depth: u32, - pub paths: Vec, -} - -impl Execute for PathCmd { - type Output = PathResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let mut result = PathResult { - from_module: self.from_module.clone(), - from_function: self.from_function.clone(), - to_module: self.to_module.clone(), - to_function: self.to_function.clone(), - max_depth: self.depth, - ..Default::default() - }; - - result.paths = find_paths( - db, - &self.from_module, - &self.from_function, - self.from_arity, - &self.to_module, - &self.to_function, - self.to_arity, - &self.project, - self.depth, - self.limit, - )?; - - Ok(result) - } -} \ No newline at end of file diff --git a/src/commands/path/execute_tests.rs b/src/commands/path/execute_tests.rs deleted file mode 100644 index 86ffbe1..0000000 --- a/src/commands/path/execute_tests.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! Execute tests for path command. - -#[cfg(test)] -mod tests { - use super::super::PathCmd; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // Controller.index -> Accounts.list_users (direct call) - crate::execute_test! { - test_name: test_path_direct_call, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - from_arity: None, - to_module: "MyApp.Accounts".to_string(), - to_function: "list_users".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - assertions: |result| { - assert_eq!(result.paths.len(), 1); - assert_eq!(result.paths[0].steps.len(), 1); - assert_eq!(result.paths[0].steps[0].caller_module, "MyApp.Controller"); - assert_eq!(result.paths[0].steps[0].callee_module, "MyApp.Accounts"); - }, - } - - // Controller.index -> Accounts.list_users -> Repo.all (2 hops) - crate::execute_test! { - test_name: test_path_two_hops, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - from_arity: None, - to_module: "MyApp.Repo".to_string(), - to_function: "all".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - assertions: |result| { - assert_eq!(result.paths.len(), 1); - assert_eq!(result.paths[0].steps.len(), 2); - }, - } - - // Controller.show -> Accounts.get_user -> Repo.get (2 hops) - // Both get_user/1 and get_user/2 call Repo.get, so 2 paths found - crate::execute_test! { - test_name: test_path_via_accounts, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "show".to_string(), - from_arity: None, - to_module: "MyApp.Repo".to_string(), - to_function: "get".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - assertions: |result| { - assert_eq!(result.paths.len(), 2); - assert!(result.paths.iter().all(|p| p.steps.len() == 2)); - }, - } - - // ========================================================================= - // Arity filtering tests - // ========================================================================= - - // Controller.show/2 -> Accounts.get_user/1 -> Repo.get (with from_arity) - crate::execute_test! { - test_name: test_path_with_from_arity, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "show".to_string(), - from_arity: Some(2), - to_module: "MyApp.Repo".to_string(), - to_function: "get".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - assertions: |result| { - // Should find paths via get_user/1 and get_user/2 - assert!(!result.paths.is_empty()); - // First step caller should be show/2 - assert!(result.paths[0].steps[0].caller_function.starts_with("show")); - }, - } - - // Controller.index/2 -> Accounts.list_users/0 (with from_arity exact match) - crate::execute_test! { - test_name: test_path_with_from_arity_exact, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - from_arity: Some(2), - to_module: "MyApp.Accounts".to_string(), - to_function: "list_users".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - assertions: |result| { - assert_eq!(result.paths.len(), 1); - // caller_function is just the name (no arity suffix in calls table) - assert_eq!(result.paths[0].steps[0].caller_function, "index"); - }, - } - - // Wrong arity should find no paths - crate::execute_no_match_test! { - test_name: test_path_with_wrong_from_arity, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - from_arity: Some(99), // Wrong arity - index is /2 - to_module: "MyApp.Accounts".to_string(), - to_function: "list_users".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - empty_field: paths, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - // No path from Repo back to Controller (acyclic) - crate::execute_no_match_test! { - test_name: test_path_no_path_exists, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Repo".to_string(), - from_function: "get".to_string(), - from_arity: None, - to_module: "MyApp.Controller".to_string(), - to_function: "index".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - empty_field: paths, - } - - // Depth 1 can't reach Repo.all from Controller.index (needs 2 hops) - crate::execute_no_match_test! { - test_name: test_path_depth_limit, - fixture: populated_db, - cmd: PathCmd { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - from_arity: None, - to_module: "MyApp.Repo".to_string(), - to_function: "all".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 1, - limit: 10, - }, - empty_field: paths, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: PathCmd, - cmd: PathCmd { - from_module: "MyApp".to_string(), - from_function: "foo".to_string(), - from_arity: None, - to_module: "MyApp".to_string(), - to_function: "bar".to_string(), - to_arity: None, - project: "test_project".to_string(), - depth: 10, - limit: 10, - }, - } -} diff --git a/src/commands/path/mod.rs b/src/commands/path/mod.rs deleted file mode 100644 index 75d4f25..0000000 --- a/src/commands/path/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find a call path between two functions -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search path --from-module MyApp.Web --from-function index \\ - --to-module MyApp.Repo --to-function get - code_search path --from-module MyApp.API --from-function create \\ - --to-module Ecto.Repo --to-function insert --depth 15")] -pub struct PathCmd { - /// Source module name - #[arg(long)] - pub from_module: String, - - /// Source function name - #[arg(long)] - pub from_function: String, - - /// Source function arity (optional) - #[arg(long)] - pub from_arity: Option, - - /// Target module name - #[arg(long)] - pub to_module: String, - - /// Target function name - #[arg(long)] - pub to_function: String, - - /// Target function arity (optional) - #[arg(long)] - pub to_arity: Option, - - /// Project to search in - #[arg(long, default_value = "default")] - pub project: String, - - /// Maximum depth to search (1-20) - #[arg(long, default_value_t = 10, value_parser = clap::value_parser!(u32).range(1..=20))] - pub depth: u32, - - /// Maximum number of paths to return (1-1000) - #[arg(short, long, default_value_t = 100, value_parser = clap::value_parser!(u32).range(1..=1000))] - pub limit: u32, -} - -impl CommandRunner for PathCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/path/output.rs b/src/commands/path/output.rs deleted file mode 100644 index 06297a0..0000000 --- a/src/commands/path/output.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! Output formatting for path command results. - -use crate::output::Outputable; -use super::execute::PathResult; - -impl Outputable for PathResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - let header = format!( - "Path from: {}.{} to: {}.{}", - self.from_module, self.from_function, self.to_module, self.to_function - ); - lines.push(header); - lines.push(format!("Max depth: {}", self.max_depth)); - lines.push(String::new()); - - if !self.paths.is_empty() { - lines.push(format!("Found {} path(s):", self.paths.len())); - for (i, path) in self.paths.iter().enumerate() { - lines.push(String::new()); - lines.push(format!("Path {}:", i + 1)); - for step in &path.steps { - let indent = " ".repeat(step.depth as usize); - let caller = format!("{}.{}", step.caller_module, step.caller_function); - let callee = format!("{}.{}/{}", step.callee_module, step.callee_function, step.callee_arity); - lines.push(format!( - "{}[{}] {} ({}:{}) -> {}", - indent, step.depth, caller, step.file, step.line, callee - )); - } - } - } else { - lines.push("No path found.".to_string()); - } - - lines.join("\n") - } -} diff --git a/src/commands/path/output_tests.rs b/src/commands/path/output_tests.rs deleted file mode 100644 index 1fe1805..0000000 --- a/src/commands/path/output_tests.rs +++ /dev/null @@ -1,122 +0,0 @@ -//! Output formatting tests for path command. - -#[cfg(test)] -mod tests { - use super::super::execute::PathResult; - use crate::queries::path::{CallPath, PathStep}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Path from: MyApp.Controller.index to: MyApp.Repo.get -Max depth: 10 - -No path found."; - - const SINGLE_PATH_TABLE: &str = "\ -Path from: MyApp.Controller.index to: MyApp.Repo.get -Max depth: 10 - -Found 1 path(s): - -Path 1: - [1] MyApp.Controller.index (lib/controller.ex:7) -> MyApp.Service.fetch/1 - [2] MyApp.Service.fetch (lib/service.ex:15) -> MyApp.Repo.get/2"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> PathResult { - PathResult { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - to_module: "MyApp.Repo".to_string(), - to_function: "get".to_string(), - max_depth: 10, - paths: vec![], - } - } - - #[fixture] - fn single_path_result() -> PathResult { - PathResult { - from_module: "MyApp.Controller".to_string(), - from_function: "index".to_string(), - to_module: "MyApp.Repo".to_string(), - to_function: "get".to_string(), - max_depth: 10, - paths: vec![CallPath { - steps: vec![ - PathStep { - depth: 1, - caller_module: "MyApp.Controller".to_string(), - caller_function: "index".to_string(), - callee_module: "MyApp.Service".to_string(), - callee_function: "fetch".to_string(), - callee_arity: 1, - file: "lib/controller.ex".to_string(), - line: 7, - }, - PathStep { - depth: 2, - caller_module: "MyApp.Service".to_string(), - caller_function: "fetch".to_string(), - callee_module: "MyApp.Repo".to_string(), - callee_function: "get".to_string(), - callee_arity: 2, - file: "lib/service.ex".to_string(), - line: 15, - }, - ], - }], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: PathResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single_path, - fixture: single_path_result, - fixture_type: PathResult, - expected: SINGLE_PATH_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_path_result, - fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_path_result, - fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: PathResult, - expected: crate::test_utils::load_output_fixture("path", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/returns/execute.rs b/src/commands/returns/execute.rs deleted file mode 100644 index 20eeeac..0000000 --- a/src/commands/returns/execute.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::ReturnsCmd; -use crate::commands::Execute; -use crate::queries::returns::{find_returns, ReturnEntry}; -use crate::types::ModuleGroupResult; - -/// A function's return type information -#[derive(Debug, Clone, Serialize)] -pub struct ReturnInfo { - pub name: String, - pub arity: i64, - pub return_type: String, - pub line: i64, -} - -impl ModuleGroupResult { - /// Build grouped result from flat ReturnEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); - - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let return_info = ReturnInfo { - name: entry.name, - arity: entry.arity, - return_type: entry.return_string, - line: entry.line, - }; - (entry.module, return_info) - }); - - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } - } -} - -impl Execute for ReturnsCmd { - type Output = ModuleGroupResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let entries = find_returns( - db, - &self.pattern, - &self.common.project, - self.common.regex, - self.module.as_deref(), - self.common.limit, - )?; - - Ok(>::from_entries( - self.pattern, - self.module, - entries, - )) - } -} diff --git a/src/commands/returns/mod.rs b/src/commands/returns/mod.rs deleted file mode 100644 index 98d7674..0000000 --- a/src/commands/returns/mod.rs +++ /dev/null @@ -1,37 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions returning a specific type pattern -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search returns \"User.t\" # Find functions returning User.t - code_search returns \"nil\" # Find functions returning nil - code_search returns \"{:error\" MyApp # Filter to module MyApp - code_search returns -r \"list\\(.*\\)\" # Regex pattern matching -")] -pub struct ReturnsCmd { - /// Type pattern to search for in return types - pub pattern: String, - - /// Module filter pattern - pub module: Option, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for ReturnsCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/returns/output.rs b/src/commands/returns/output.rs deleted file mode 100644 index f4c904d..0000000 --- a/src/commands/returns/output.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Output formatting for returns command results. - -use crate::output::TableFormatter; -use crate::types::ModuleGroupResult; -use super::execute::ReturnInfo; - -impl TableFormatter for ModuleGroupResult { - type Entry = ReturnInfo; - - fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); - format!("Functions returning \"{}\"", pattern) - } - - fn format_empty_message(&self) -> String { - "No functions found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} function(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, return_info: &ReturnInfo, _module: &str, _file: &str) -> String { - format!("{}/{} → {}", return_info.name, return_info.arity, return_info.return_type) - } -} diff --git a/src/commands/reverse_trace/cli_tests.rs b/src/commands/reverse_trace/cli_tests.rs deleted file mode 100644 index c14fc9c..0000000 --- a/src/commands/reverse_trace/cli_tests.rs +++ /dev/null @@ -1,115 +0,0 @@ -//! CLI parsing tests for reverse-trace command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "reverse-trace", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_required_arg_test! { - command: "reverse-trace", - test_name: test_requires_function, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "reverse-trace", - variant: ReverseTrace, - test_name: test_with_module_and_function, - args: ["MyApp.Repo", "get"], - field: module, - expected: "MyApp.Repo", - } - - crate::cli_option_test! { - command: "reverse-trace", - variant: ReverseTrace, - test_name: test_function_name, - args: ["MyApp.Repo", "get"], - field: function, - expected: "get", - } - - crate::cli_option_test! { - command: "reverse-trace", - variant: ReverseTrace, - test_name: test_with_depth, - args: ["MyApp", "foo", "--depth", "10"], - field: depth, - expected: 10, - } - - crate::cli_option_test! { - command: "reverse-trace", - variant: ReverseTrace, - test_name: test_with_limit, - args: ["MyApp", "foo", "--limit", "50"], - field: common.limit, - expected: 50, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "reverse-trace", - variant: ReverseTrace, - required_args: ["MyApp", "foo"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Edge case tests (depth validation - different from standard limit) - // ========================================================================= - - #[rstest] - fn test_depth_default() { - let args = Args::try_parse_from(["code_search", "reverse-trace", "MyApp.Repo", "get"]) - .unwrap(); - match args.command { - crate::commands::Command::ReverseTrace(cmd) => { - assert_eq!(cmd.depth, 5); - } - _ => panic!("Expected ReverseTrace command"), - } - } - - #[rstest] - fn test_depth_zero_rejected() { - let result = - Args::try_parse_from(["code_search", "reverse-trace", "MyApp", "foo", "--depth", "0"]); - assert!(result.is_err()); - } - - #[rstest] - fn test_depth_exceeds_max_rejected() { - let result = Args::try_parse_from([ - "code_search", - "reverse-trace", - "MyApp", - "foo", - "--depth", - "21", - ]); - assert!(result.is_err()); - } -} diff --git a/src/commands/reverse_trace/execute.rs b/src/commands/reverse_trace/execute.rs deleted file mode 100644 index ecb9518..0000000 --- a/src/commands/reverse_trace/execute.rs +++ /dev/null @@ -1,157 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; - -use super::ReverseTraceCmd; -use crate::commands::Execute; -use crate::queries::reverse_trace::{reverse_trace_calls, ReverseTraceStep}; -use crate::types::{TraceDirection, TraceEntry, TraceResult}; - -impl TraceResult { - /// Build a flattened reverse-trace from ReverseTraceStep objects - pub fn from_steps( - target_module: String, - target_function: String, - max_depth: u32, - steps: Vec, - ) -> Self { - let mut entries = Vec::new(); - let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); - - if steps.is_empty() { - return Self::empty(target_module, target_function, max_depth, TraceDirection::Backward); - } - - // Group steps by depth - let mut by_depth: HashMap> = HashMap::new(); - for step in &steps { - by_depth.entry(step.depth).or_default().push(step); - } - - // Process depth 1 (direct callers of target function) - if let Some(depth1_steps) = by_depth.get(&1) { - let mut filter = crate::dedup::DeduplicationFilter::new(); - - for step in depth1_steps { - let caller_key = ( - step.caller_module.clone(), - step.caller_function.clone(), - step.caller_arity, - 1i64, - ); - - // Add caller as root entry if not already added - if filter.should_process(caller_key.clone()) { - let entry_idx = entries.len(); - entries.push(TraceEntry { - module: step.caller_module.clone(), - function: step.caller_function.clone(), - arity: step.caller_arity, - kind: step.caller_kind.clone(), - start_line: step.caller_start_line, - end_line: step.caller_end_line, - file: step.file.clone(), - depth: 1, - line: step.line, - parent_index: None, - }); - entry_index_map.insert(caller_key, entry_idx); - } - } - } - - // Process deeper levels (additional callers) - for depth in 2..=max_depth as i64 { - if let Some(depth_steps) = by_depth.get(&depth) { - let mut filter = crate::dedup::DeduplicationFilter::new(); - - for step in depth_steps { - let caller_key = ( - step.caller_module.clone(), - step.caller_function.clone(), - step.caller_arity, - depth, - ); - - // Find parent index (the callee at previous depth, which is what called this caller) - let parent_key = ( - step.callee_module.clone(), - step.callee_function.clone(), - step.callee_arity, - depth - 1, - ); - - let parent_index = entry_index_map.get(&parent_key).copied(); - - if filter.should_process(caller_key.clone()) && parent_index.is_some() { - let entry_idx = entries.len(); - entries.push(TraceEntry { - module: step.caller_module.clone(), - function: step.caller_function.clone(), - arity: step.caller_arity, - kind: step.caller_kind.clone(), - start_line: step.caller_start_line, - end_line: step.caller_end_line, - file: step.file.clone(), - depth, - line: step.line, - parent_index, - }); - entry_index_map.insert(caller_key, entry_idx); - } - } - } - } - - let total_items = entries.len(); - - Self { - module: target_module, - function: target_function, - max_depth, - direction: TraceDirection::Backward, - total_items, - entries, - } - } -} - -impl Execute for ReverseTraceCmd { - type Output = TraceResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let steps = reverse_trace_calls( - db, - &self.module, - &self.function, - self.arity, - &self.common.project, - self.common.regex, - self.depth, - self.common.limit, - )?; - - Ok(TraceResult::from_steps( - self.module, - self.function, - self.depth, - steps, - )) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_empty_reverse_trace() { - let result = TraceResult::from_steps( - "TestModule".to_string(), - "test_func".to_string(), - 5, - vec![], - ); - assert_eq!(result.total_items, 0); - assert_eq!(result.entries.len(), 0); - } -} diff --git a/src/commands/reverse_trace/execute_tests.rs b/src/commands/reverse_trace/execute_tests.rs deleted file mode 100644 index 082086a..0000000 --- a/src/commands/reverse_trace/execute_tests.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! Execute tests for reverse-trace command. - -#[cfg(test)] -mod tests { - use super::super::ReverseTraceCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // At depth 1: Accounts.get_user/1, Accounts.get_user/2, Service.do_fetch all call Repo.get - crate::execute_test! { - test_name: test_reverse_trace_single_depth, - fixture: populated_db, - cmd: ReverseTraceCmd { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - arity: None, - depth: 1, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3); - // All entries at depth 1 are direct callers of the target - assert!(result.entries.iter().all(|e| e.depth == 1)); - }, - } - - // Depth 2 adds: Controller.show -> get_user, Service.fetch -> do_fetch - crate::execute_test! { - test_name: test_reverse_trace_multiple_depths, - fixture: populated_db, - cmd: ReverseTraceCmd { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - arity: None, - depth: 2, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 5); - }, - } - - // Trace back from Notifier.send_email (leaf): notify->send_email, process->notify, create->process - crate::execute_test! { - test_name: test_reverse_trace_from_leaf, - fixture: populated_db, - cmd: ReverseTraceCmd { - module: "MyApp.Notifier".to_string(), - function: "send_email".to_string(), - arity: None, - depth: 5, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_reverse_trace_no_match, - fixture: populated_db, - cmd: ReverseTraceCmd { - module: "NonExistent".to_string(), - function: "foo".to_string(), - arity: None, - depth: 5, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: entries, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: ReverseTraceCmd, - cmd: ReverseTraceCmd { - module: "MyApp".to_string(), - function: "foo".to_string(), - arity: None, - depth: 5, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/reverse_trace/mod.rs b/src/commands/reverse_trace/mod.rs deleted file mode 100644 index 9b974b9..0000000 --- a/src/commands/reverse_trace/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Trace call chains backwards - who calls the callers of a target -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search reverse-trace MyApp.Repo get # Who ultimately calls Repo.get? - code_search reverse-trace Ecto.Repo insert --depth 10 # Deeper traversal - code_search reverse-trace -r 'MyApp\\..*' 'handle_.*' # Regex pattern -")] -pub struct ReverseTraceCmd { - /// Target module name (exact match or pattern with --regex) - pub module: String, - - /// Target function name (exact match or pattern with --regex) - pub function: String, - - /// Function arity (optional) - #[arg(short, long)] - pub arity: Option, - - /// Maximum depth to traverse (1-20) - #[arg(long, default_value_t = 5, value_parser = clap::value_parser!(u32).range(1..=20))] - pub depth: u32, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for ReverseTraceCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/reverse_trace/output.rs b/src/commands/reverse_trace/output.rs deleted file mode 100644 index 0d1abbc..0000000 --- a/src/commands/reverse_trace/output.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Output formatting for reverse-trace command results. -//! -//! The output implementation is shared with the trace command in trace/output.rs. -//! Both commands use TraceResult with a direction field to determine rendering. diff --git a/src/commands/reverse_trace/output_tests.rs b/src/commands/reverse_trace/output_tests.rs deleted file mode 100644 index ab4cbe5..0000000 --- a/src/commands/reverse_trace/output_tests.rs +++ /dev/null @@ -1,138 +0,0 @@ -//! Output formatting tests for reverse-trace command. - -#[cfg(test)] -mod tests { - use crate::types::{TraceDirection, TraceEntry, TraceResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Reverse trace to: MyApp.Repo.get -Max depth: 5 - -No callers found."; - - const SINGLE_TABLE: &str = "\ -Reverse trace to: MyApp.Repo.get -Max depth: 5 - -Found 1 caller(s) in chain: - -MyApp.Service.fetch/1 [def] (service.ex:L10:20)"; - - const MULTI_DEPTH_TABLE: &str = "\ -Reverse trace to: MyApp.Repo.get -Max depth: 5 - -Found 2 caller(s) in chain: - -MyApp.Service.fetch/1 [def] (service.ex:L10:20) - ← @ L7 MyApp.Controller.index/1 [def] (controller.ex:L5:12)"; - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> TraceResult { - TraceResult { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - max_depth: 5, - direction: TraceDirection::Backward, - total_items: 0, - entries: vec![], - } - } - - #[fixture] - fn single_depth_result() -> TraceResult { - TraceResult { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - max_depth: 5, - direction: TraceDirection::Backward, - total_items: 1, - entries: vec![ - // Direct caller at depth 1 - TraceEntry { - module: "MyApp.Service".to_string(), - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "service.ex".to_string(), - depth: 1, - line: 15, - parent_index: None, - }, - ], - } - } - - #[fixture] - fn multi_depth_result() -> TraceResult { - TraceResult { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - max_depth: 5, - direction: TraceDirection::Backward, - total_items: 2, - entries: vec![ - TraceEntry { - module: "MyApp.Service".to_string(), - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "service.ex".to_string(), - depth: 1, - line: 15, - parent_index: None, - }, - TraceEntry { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 5, - end_line: 12, - file: "controller.ex".to_string(), - depth: 2, - line: 7, - parent_index: Some(0), - }, - ], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - #[rstest] - fn test_empty_reverse_trace(empty_result: TraceResult) { - use crate::output::Outputable; - let output = empty_result.to_table(); - assert_eq!(output, EMPTY_TABLE); - } - - #[rstest] - fn test_single_depth_reverse_trace(single_depth_result: TraceResult) { - use crate::output::Outputable; - let output = single_depth_result.to_table(); - assert_eq!(output, SINGLE_TABLE); - } - - #[rstest] - fn test_multi_depth_reverse_trace(multi_depth_result: TraceResult) { - use crate::output::Outputable; - let output = multi_depth_result.to_table(); - assert_eq!(output, MULTI_DEPTH_TABLE); - } -} diff --git a/src/commands/search/cli_tests.rs b/src/commands/search/cli_tests.rs deleted file mode 100644 index e321f24..0000000 --- a/src/commands/search/cli_tests.rs +++ /dev/null @@ -1,92 +0,0 @@ -//! CLI parsing tests for search command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use crate::commands::search::SearchKind; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "search", - test_name: test_search_requires_pattern, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "search", - variant: Search, - test_name: test_search_with_pattern, - args: ["User"], - field: pattern, - expected: "User", - } - - crate::cli_option_test! { - command: "search", - variant: Search, - test_name: test_search_with_project_filter, - args: ["User", "--project", "my_app"], - field: common.project, - expected: "my_app", - } - - crate::cli_option_test! { - command: "search", - variant: Search, - test_name: test_search_with_limit, - args: ["User", "--limit", "50"], - field: common.limit, - expected: 50, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "search", - variant: Search, - required_args: ["User"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Edge case tests (kept as regular tests due to matches! macro usage) - // ========================================================================= - - #[rstest] - fn test_search_kind_default_is_modules() { - let args = Args::try_parse_from(["code_search", "search", "test"]).unwrap(); - match args.command { - crate::commands::Command::Search(cmd) => { - assert!(matches!(cmd.kind, SearchKind::Modules)); - } - _ => panic!("Expected Search command"), - } - } - - #[rstest] - fn test_search_kind_functions() { - let args = - Args::try_parse_from(["code_search", "search", "get_", "--kind", "functions"]).unwrap(); - match args.command { - crate::commands::Command::Search(cmd) => { - assert!(matches!(cmd.kind, SearchKind::Functions)); - } - _ => panic!("Expected Search command"), - } - } -} diff --git a/src/commands/search/execute.rs b/src/commands/search/execute.rs deleted file mode 100644 index 410a224..0000000 --- a/src/commands/search/execute.rs +++ /dev/null @@ -1,93 +0,0 @@ -use std::collections::BTreeMap; -use std::error::Error; - -use serde::Serialize; - -use super::{SearchCmd, SearchKind}; -use crate::commands::Execute; -use crate::queries::search::{search_functions, search_modules, FunctionResult as RawFunctionResult, ModuleResult}; - -/// A function found in search results -#[derive(Debug, Clone, Serialize)] -pub struct SearchFunc { - pub name: String, - pub arity: i64, - #[serde(skip_serializing_if = "String::is_empty")] - pub return_type: String, -} - -/// A module containing functions in search results -#[derive(Debug, Clone, Serialize)] -pub struct SearchFuncModule { - pub name: String, - pub functions: Vec, -} - -/// Result of the search command execution -#[derive(Debug, Default, Serialize)] -pub struct SearchResult { - pub pattern: String, - pub kind: String, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub modules: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub total_functions: Option, - #[serde(skip_serializing_if = "Vec::is_empty")] - pub function_modules: Vec, -} - -impl SearchResult { - /// Build grouped function result from flat list - fn from_functions(pattern: String, functions: Vec) -> Self { - let total = functions.len(); - - // Group by module (BTreeMap for consistent ordering) - let mut module_map: BTreeMap> = BTreeMap::new(); - - for func in functions { - let search_func = SearchFunc { - name: func.name, - arity: func.arity, - return_type: func.return_type, - }; - - module_map.entry(func.module).or_default().push(search_func); - } - - let function_modules: Vec = module_map - .into_iter() - .map(|(name, functions)| SearchFuncModule { name, functions }) - .collect(); - - SearchResult { - pattern, - kind: "functions".to_string(), - modules: vec![], - total_functions: if total > 0 { Some(total) } else { None }, - function_modules, - } - } -} - -impl Execute for SearchCmd { - type Output = SearchResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - match self.kind { - SearchKind::Modules => { - let modules = search_modules(db, &self.pattern, &self.common.project, self.common.limit, self.common.regex)?; - Ok(SearchResult { - pattern: self.pattern, - kind: "modules".to_string(), - modules, - total_functions: None, - function_modules: vec![], - }) - } - SearchKind::Functions => { - let functions = search_functions(db, &self.pattern, &self.common.project, self.common.limit, self.common.regex)?; - Ok(SearchResult::from_functions(self.pattern, functions)) - } - } - } -} \ No newline at end of file diff --git a/src/commands/search/execute_tests.rs b/src/commands/search/execute_tests.rs deleted file mode 100644 index 2bb5361..0000000 --- a/src/commands/search/execute_tests.rs +++ /dev/null @@ -1,204 +0,0 @@ -//! Execute tests for search command. - -#[cfg(test)] -mod tests { - use super::super::{SearchCmd, SearchKind}; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: type_signatures, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // 3 modules in type_signatures: Accounts, Users, Repo - crate::execute_test! { - test_name: test_search_modules_all, - fixture: populated_db, - cmd: SearchCmd { - pattern: "MyApp".to_string(), - kind: SearchKind::Modules, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.kind, "modules"); - assert_eq!(result.modules.len(), 3); - }, - } - - // Functions with "user": get_user/1, get_user/2, list_users, create_user = 4 - crate::execute_test! { - test_name: test_search_functions_all, - fixture: populated_db, - cmd: SearchCmd { - pattern: "user".to_string(), - kind: SearchKind::Functions, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.kind, "functions"); - assert_eq!(result.total_functions, Some(4)); - }, - } - - // Functions containing "get": get_user/1, get_user/2, get_by_email, Repo.get = 4 - crate::execute_test! { - test_name: test_search_functions_specific, - fixture: populated_db, - cmd: SearchCmd { - pattern: "get".to_string(), - kind: SearchKind::Functions, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_functions, Some(4)); - }, - } - - crate::execute_test! { - test_name: test_search_functions_with_regex, - fixture: populated_db, - cmd: SearchCmd { - pattern: "^get_user$".to_string(), - kind: SearchKind::Functions, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_functions, Some(2)); - // All functions should be named get_user - for module in &result.function_modules { - for f in &module.functions { - assert_eq!(f.name, "get_user"); - } - } - }, - } - - // Modules ending in Accounts or Users - crate::execute_test! { - test_name: test_search_modules_with_regex, - fixture: populated_db, - cmd: SearchCmd { - pattern: "\\.(Accounts|Users)$".to_string(), - kind: SearchKind::Modules, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.modules.len(), 2); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_search_modules_no_match, - fixture: populated_db, - cmd: SearchCmd { - pattern: "NonExistent".to_string(), - kind: SearchKind::Modules, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: modules, - } - - crate::execute_no_match_test! { - test_name: test_search_regex_no_match, - fixture: populated_db, - cmd: SearchCmd { - pattern: "^xyz".to_string(), - kind: SearchKind::Functions, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - empty_field: function_modules, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_all_match_test! { - test_name: test_search_modules_with_project_filter, - fixture: populated_db, - cmd: SearchCmd { - pattern: "App".to_string(), - kind: SearchKind::Modules, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - collection: modules, - condition: |m| m.project == "test_project", - } - - crate::execute_test! { - test_name: test_search_with_limit, - fixture: populated_db, - cmd: SearchCmd { - pattern: "user".to_string(), - kind: SearchKind::Functions, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 1, - }, - }, - assertions: |result| { - // Limit applies to raw results before grouping - assert_eq!(result.total_functions, Some(1)); - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: SearchCmd, - cmd: SearchCmd { - pattern: "test".to_string(), - kind: SearchKind::Modules, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/search/mod.rs b/src/commands/search/mod.rs deleted file mode 100644 index 3b4c2fa..0000000 --- a/src/commands/search/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::{Args, ValueEnum}; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// What to search for -#[derive(Debug, Clone, Copy, Default, ValueEnum)] -pub enum SearchKind { - /// Search for modules - #[default] - Modules, - /// Search for functions - Functions, -} - -/// Search for modules or functions by name pattern -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search search User # Find modules containing 'User' - code_search search get_ -k functions # Find functions starting with 'get_' - code_search search -r '^MyApp\\.API' # Regex match for module prefix -")] -pub struct SearchCmd { - /// Pattern to search for (substring match by default, regex with --regex) - pub pattern: String, - - /// What to search for - #[arg(short, long, value_enum, default_value_t = SearchKind::Modules)] - pub kind: SearchKind, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for SearchCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/search/output.rs b/src/commands/search/output.rs deleted file mode 100644 index b147d3c..0000000 --- a/src/commands/search/output.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Output formatting for search command results. - -use crate::output::Outputable; -use super::execute::SearchResult; - -impl Outputable for SearchResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - lines.push(format!("Search: {} ({})", self.pattern, self.kind)); - lines.push(String::new()); - - if !self.modules.is_empty() { - lines.push(format!("Modules ({}):", self.modules.len())); - for m in &self.modules { - lines.push(format!(" {}", m.name)); - } - } - - if !self.function_modules.is_empty() { - let total = self.total_functions.unwrap_or(0); - lines.push(format!( - "Functions ({}) in {} module(s):", - total, - self.function_modules.len() - )); - lines.push(String::new()); - - for module in &self.function_modules { - lines.push(format!("{}:", module.name)); - for f in &module.functions { - let sig = if f.return_type.is_empty() { - format!("{}/{}", f.name, f.arity) - } else { - format!("{}/{} -> {}", f.name, f.arity, f.return_type) - }; - lines.push(format!(" {}", sig)); - } - } - } - - if self.modules.is_empty() && self.function_modules.is_empty() { - lines.push("No results found.".to_string()); - } - - lines.join("\n") - } -} diff --git a/src/commands/search/output_tests.rs b/src/commands/search/output_tests.rs deleted file mode 100644 index 8a5785a..0000000 --- a/src/commands/search/output_tests.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Output formatting tests for search command. - -#[cfg(test)] -mod tests { - use super::super::execute::{SearchFunc, SearchFuncModule, SearchResult}; - use crate::queries::search::ModuleResult; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Search: test (modules) - -No results found."; - - const MODULES_TABLE: &str = "\ -Search: MyApp (modules) - -Modules (2): - MyApp.Accounts - MyApp.Users"; - - const FUNCTIONS_TABLE: &str = "\ -Search: get_ (functions) - -Functions (1) in 1 module(s): - -MyApp.Accounts: - get_user/1 -> User.t()"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> SearchResult { - SearchResult { - pattern: "test".to_string(), - kind: "modules".to_string(), - modules: vec![], - total_functions: None, - function_modules: vec![], - } - } - - #[fixture] - fn modules_result() -> SearchResult { - SearchResult { - pattern: "MyApp".to_string(), - kind: "modules".to_string(), - modules: vec![ - ModuleResult { - project: "default".to_string(), - name: "MyApp.Accounts".to_string(), - source: "unknown".to_string(), - }, - ModuleResult { - project: "default".to_string(), - name: "MyApp.Users".to_string(), - source: "unknown".to_string(), - }, - ], - total_functions: None, - function_modules: vec![], - } - } - - #[fixture] - fn functions_result() -> SearchResult { - SearchResult { - pattern: "get_".to_string(), - kind: "functions".to_string(), - modules: vec![], - total_functions: Some(1), - function_modules: vec![SearchFuncModule { - name: "MyApp.Accounts".to_string(), - functions: vec![SearchFunc { - name: "get_user".to_string(), - arity: 1, - return_type: "User.t()".to_string(), - }], - }], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: SearchResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_modules, - fixture: modules_result, - fixture_type: SearchResult, - expected: MODULES_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_functions, - fixture: functions_result, - fixture_type: SearchResult, - expected: FUNCTIONS_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: modules_result, - fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "modules.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: modules_result, - fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "modules.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: SearchResult, - expected: crate::test_utils::load_output_fixture("search", "empty.toon"), - format: Toon, - } -} diff --git a/src/commands/setup/execute.rs b/src/commands/setup/execute.rs deleted file mode 100644 index ee80a88..0000000 --- a/src/commands/setup/execute.rs +++ /dev/null @@ -1,887 +0,0 @@ -use std::error::Error; -use std::fs; -use cozo::DbInstance; -use include_dir::{include_dir, Dir}; -use serde::Serialize; - -use super::SetupCmd; -use crate::commands::Execute; -use crate::queries::schema; - -/// Embedded skill templates directory -static SKILL_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/skills"); - -/// Embedded agent templates directory -static AGENT_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/agents"); - -/// Embedded hook templates directory -static HOOK_TEMPLATES: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates/hooks"); - -/// Status of a database relation (table) -#[derive(Debug, Clone, Serialize)] -pub enum RelationState { - #[serde(rename = "created")] - Created, - #[serde(rename = "exists")] - AlreadyExists, - #[serde(rename = "would_create")] - WouldCreate, -} - -/// Status information for a single database relation -#[derive(Debug, Clone, Serialize)] -pub struct RelationStatus { - pub name: String, - pub status: RelationState, -} - -/// Status of a template file (skill or agent) -#[derive(Debug, Clone, Serialize)] -pub enum TemplateFileState { - #[serde(rename = "installed")] - Installed, - #[serde(rename = "skipped")] - Skipped, - #[serde(rename = "overwritten")] - Overwritten, -} - -/// Status information for a single template file -#[derive(Debug, Clone, Serialize)] -pub struct TemplateFileStatus { - pub path: String, - pub status: TemplateFileState, -} - -/// Result of templates installation -#[derive(Debug, Serialize)] -pub struct TemplatesInstallResult { - pub skills: Vec, - pub agents: Vec, - pub skills_installed: usize, - pub skills_skipped: usize, - pub skills_overwritten: usize, - pub agents_installed: usize, - pub agents_skipped: usize, - pub agents_overwritten: usize, -} - -/// Result of git hooks installation -#[derive(Debug, Serialize)] -pub struct HooksInstallResult { - pub hooks: Vec, - pub hooks_installed: usize, - pub hooks_skipped: usize, - pub hooks_overwritten: usize, - pub git_config: Vec, -} - -/// Status of a git config setting -#[derive(Debug, Clone, Serialize)] -pub struct GitConfigStatus { - pub key: String, - pub value: String, - pub set: bool, -} - -/// Result of the setup command execution -#[derive(Debug, Serialize)] -pub struct SetupResult { - pub relations: Vec, - pub created_new: bool, - pub dry_run: bool, - #[serde(skip_serializing_if = "Option::is_none")] - pub templates: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub hooks: Option, -} - -/// Recursively process a directory and install all files -fn process_dir( - dir: &include_dir::Dir, - base_path: &std::path::Path, - force: bool, - files: &mut Vec, - installed_count: &mut usize, - skipped_count: &mut usize, - overwritten_count: &mut usize, -) -> Result<(), Box> { - for entry in dir.entries() { - match entry { - include_dir::DirEntry::Dir(subdir) => { - // Recursively process subdirectory - process_dir(subdir, base_path, force, files, installed_count, skipped_count, overwritten_count)?; - } - include_dir::DirEntry::File(file) => { - let relative_path = file.path(); - let target_path = base_path.join(relative_path); - - // Create parent directories if needed - if let Some(parent) = target_path.parent() { - fs::create_dir_all(parent)?; - } - - // Check if file exists - let exists = target_path.exists(); - let status = if exists && !force { - // Skip existing files unless force is enabled - *skipped_count += 1; - TemplateFileState::Skipped - } else { - // Write file contents - fs::write(&target_path, file.contents())?; - - if exists { - *overwritten_count += 1; - TemplateFileState::Overwritten - } else { - *installed_count += 1; - TemplateFileState::Installed - } - }; - - files.push(TemplateFileStatus { - path: relative_path.display().to_string(), - status, - }); - } - } - } - Ok(()) -} - -/// Install templates (skills and agents) to .claude/ in the given base directory -fn install_templates_to(base_dir: &std::path::Path, force: bool) -> Result> { - let claude_dir = base_dir.join(".claude"); - let skills_dir = claude_dir.join("skills"); - let agents_dir = claude_dir.join("agents"); - - // Create .claude/skills/ and .claude/agents/ directories - fs::create_dir_all(&skills_dir)?; - fs::create_dir_all(&agents_dir)?; - - // Process skills - let mut skills_files = Vec::new(); - let mut skills_installed = 0; - let mut skills_skipped = 0; - let mut skills_overwritten = 0; - - process_dir( - &SKILL_TEMPLATES, - &skills_dir, - force, - &mut skills_files, - &mut skills_installed, - &mut skills_skipped, - &mut skills_overwritten, - )?; - - // Process agents - let mut agents_files = Vec::new(); - let mut agents_installed = 0; - let mut agents_skipped = 0; - let mut agents_overwritten = 0; - - process_dir( - &AGENT_TEMPLATES, - &agents_dir, - force, - &mut agents_files, - &mut agents_installed, - &mut agents_skipped, - &mut agents_overwritten, - )?; - - Ok(TemplatesInstallResult { - skills: skills_files, - agents: agents_files, - skills_installed, - skills_skipped, - skills_overwritten, - agents_installed, - agents_skipped, - agents_overwritten, - }) -} - -/// Install templates to .claude/ -fn install_templates(force: bool) -> Result> { - // Get current working directory - let cwd = std::env::current_dir()?; - install_templates_to(&cwd, force) -} - -/// Install git hooks to .git/hooks/ -fn install_hooks( - force: bool, - project_name: Option, - mix_env: Option, -) -> Result> { - use std::process::Command; - - // Check if we're in a git repository - let git_dir = Command::new("git") - .args(["rev-parse", "--git-dir"]) - .output()?; - - if !git_dir.status.success() { - return Err("Not in a git repository".into()); - } - - let git_dir_path = String::from_utf8(git_dir.stdout)?.trim().to_string(); - let hooks_dir = std::path::Path::new(&git_dir_path).join("hooks"); - - // Create hooks directory if it doesn't exist - fs::create_dir_all(&hooks_dir)?; - - // Process hook files - let mut hooks_files = Vec::new(); - let mut hooks_installed = 0; - let mut hooks_skipped = 0; - let mut hooks_overwritten = 0; - - process_dir( - &HOOK_TEMPLATES, - &hooks_dir, - force, - &mut hooks_files, - &mut hooks_installed, - &mut hooks_skipped, - &mut hooks_overwritten, - )?; - - // Make hooks executable - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - for file_status in &hooks_files { - let hook_path = hooks_dir.join(&file_status.path); - if hook_path.exists() { - let mut perms = fs::metadata(&hook_path)?.permissions(); - perms.set_mode(0o755); - fs::set_permissions(&hook_path, perms)?; - } - } - } - - // Configure git settings - let mut git_config = Vec::new(); - - // Build config list (only set values that are provided) - let mut configs: Vec<(&str, String)> = Vec::new(); - - // Only set project name if explicitly provided - if let Some(name) = project_name { - configs.push(("code-search.project-name", name)); - } - - // Set mix-env (default to "dev" if not provided) - configs.push(( - "code-search.mix-env", - mix_env.unwrap_or_else(|| "dev".to_string()), - )); - - for (key, value) in configs { - let output = Command::new("git") - .args(["config", key, &value]) - .output()?; - - git_config.push(GitConfigStatus { - key: key.to_string(), - value, - set: output.status.success(), - }); - } - - Ok(HooksInstallResult { - hooks: hooks_files, - hooks_installed, - hooks_skipped, - hooks_overwritten, - git_config, - }) -} - -impl Execute for SetupCmd { - type Output = SetupResult; - - fn execute(self, db: &DbInstance) -> Result> { - let mut relations = Vec::new(); - - if self.dry_run { - // In dry-run mode, just show what would be created - for rel_name in schema::relation_names() { - relations.push(RelationStatus { - name: rel_name.to_string(), - status: RelationState::WouldCreate, - }); - } - - return Ok(SetupResult { - relations, - created_new: false, - dry_run: true, - templates: None, - hooks: None, - }); - } - - // Note: The --force flag only affects template and hook file overwriting. - // It does not drop and recreate database schemas. Schema creation is idempotent - // and will skip existing relations regardless of the --force flag. - - // Create schema - let schema_results = schema::create_schema(db)?; - - for schema_result in schema_results { - let status = if schema_result.created { - RelationState::Created - } else { - RelationState::AlreadyExists - }; - - relations.push(RelationStatus { - name: schema_result.relation, - status, - }); - } - - // Check if we created new relations - let created_new = relations - .iter() - .any(|r| matches!(r.status, RelationState::Created)); - - // Install templates (skills and agents) if requested - let templates = if self.install_skills { - Some(install_templates(self.force)?) - } else { - None - }; - - // Install git hooks if requested - let hooks = if self.install_hooks { - Some(install_hooks( - self.force, - self.project_name, - self.mix_env, - )?) - } else { - None - }; - - Ok(SetupResult { - relations, - created_new, - dry_run: false, - templates, - hooks, - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::db::open_db; - use rstest::{fixture, rstest}; - use tempfile::NamedTempFile; - - #[fixture] - fn db_file() -> NamedTempFile { - NamedTempFile::new().expect("Failed to create temp db file") - } - - #[rstest] - fn test_setup_creates_all_relations(db_file: NamedTempFile) { - let cmd = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db).expect("Setup should succeed"); - - // Should create 7 relations - assert_eq!(result.relations.len(), 7); - - // All should be created - assert!(result - .relations - .iter() - .all(|r| matches!(r.status, RelationState::Created))); - - assert!(result.created_new); - assert!(result.templates.is_none()); - assert!(result.hooks.is_none()); - } - - #[rstest] - fn test_setup_idempotent(db_file: NamedTempFile) { - let db = open_db(db_file.path()).expect("Failed to open db"); - - // First setup - let cmd1 = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - let result1 = cmd1.execute(&db).expect("First setup should succeed"); - assert!(result1.created_new); - - // Second setup should find existing relations - let cmd2 = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - let result2 = cmd2.execute(&db).expect("Second setup should succeed"); - - // Should still have 7 relations, but all already existing - assert_eq!(result2.relations.len(), 7); - assert!(result2 - .relations - .iter() - .all(|r| matches!(r.status, RelationState::AlreadyExists))); - - assert!(!result2.created_new); - } - - #[rstest] - fn test_setup_dry_run(db_file: NamedTempFile) { - let cmd = SetupCmd { - force: false, - dry_run: true, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db).expect("Setup should succeed"); - - assert!(result.dry_run); - assert_eq!(result.relations.len(), 7); - - // All should be in would_create state - assert!(result - .relations - .iter() - .all(|r| matches!(r.status, RelationState::WouldCreate))); - - // Should not have actually created anything - assert!(!result.created_new); - } - - #[rstest] - fn test_setup_relations_have_correct_names(db_file: NamedTempFile) { - let cmd = SetupCmd { - force: false, - dry_run: true, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db).expect("Setup should succeed"); - - let relation_names: Vec<_> = result.relations.iter().map(|r| r.name.as_str()).collect(); - - assert!(relation_names.contains(&"modules")); - assert!(relation_names.contains(&"functions")); - assert!(relation_names.contains(&"calls")); - assert!(relation_names.contains(&"struct_fields")); - assert!(relation_names.contains(&"function_locations")); - assert!(relation_names.contains(&"specs")); - assert!(relation_names.contains(&"types")); - } - - #[test] - fn test_install_templates() { - use tempfile::TempDir; - - // Create a temporary directory - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - - // Install templates directly to temp directory - let result = install_templates_to(temp_dir.path(), false) - .expect("Install should succeed"); - - // All files should be installed (not skipped or overwritten) - assert_eq!(result.skills_installed, 34, "Should install all 34 skill files"); - assert_eq!(result.skills_skipped, 0); - assert_eq!(result.skills_overwritten, 0); - - assert_eq!(result.agents_installed, 1, "Should install 1 agent file"); - assert_eq!(result.agents_skipped, 0); - assert_eq!(result.agents_overwritten, 0); - - // Verify .claude/skills and .claude/agents directories were created - assert!(temp_dir.path().join(".claude").join("skills").exists()); - assert!(temp_dir.path().join(".claude").join("agents").exists()); - } - - #[test] - fn test_install_templates_skips_existing() { - use tempfile::TempDir; - - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - - // First installation - let result1 = install_templates_to(temp_dir.path(), false) - .expect("First install should succeed"); - assert_eq!(result1.skills_installed, 34); - assert_eq!(result1.agents_installed, 1); - - // Second installation without force - should skip all files - let result2 = install_templates_to(temp_dir.path(), false) - .expect("Second install should succeed"); - assert_eq!(result2.skills_installed, 0, "Should not install any skill files"); - assert_eq!(result2.skills_skipped, 34, "Should skip all 34 existing skill files"); - assert_eq!(result2.skills_overwritten, 0); - - assert_eq!(result2.agents_installed, 0, "Should not install any agent files"); - assert_eq!(result2.agents_skipped, 1, "Should skip the existing agent file"); - assert_eq!(result2.agents_overwritten, 0); - } - - #[test] - fn test_install_templates_force_overwrites() { - use tempfile::TempDir; - - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - - // First installation - let result1 = install_templates_to(temp_dir.path(), false) - .expect("First install should succeed"); - assert_eq!(result1.skills_installed, 34); - assert_eq!(result1.agents_installed, 1); - - // Second installation with force - should overwrite all files - let result2 = install_templates_to(temp_dir.path(), true) - .expect("Second install with force should succeed"); - assert_eq!(result2.skills_installed, 0, "Should not install new skill files"); - assert_eq!(result2.skills_skipped, 0, "Should not skip any skill files"); - assert_eq!(result2.skills_overwritten, 34, "Should overwrite all 34 existing skill files"); - - assert_eq!(result2.agents_installed, 0, "Should not install new agent files"); - assert_eq!(result2.agents_skipped, 0, "Should not skip any agent files"); - assert_eq!(result2.agents_overwritten, 1, "Should overwrite the existing agent file"); - } - - #[rstest] - fn test_no_templates_when_not_requested(db_file: NamedTempFile) { - let cmd = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: false, - project_name: None, - mix_env: None, - }; - - let db = open_db(db_file.path()).expect("Failed to open db"); - let result = cmd.execute(&db).expect("Setup should succeed"); - - // Templates and hooks should be None when not requested - assert!(result.templates.is_none()); - assert!(result.hooks.is_none()); - } - - #[test] - #[serial_test::serial] - fn test_install_hooks_in_git_repo() { - use std::process::Command; - use tempfile::TempDir; - - // Create a temporary directory and initialize a git repo - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let temp_path = temp_dir.path(); - - // Initialize git repo - Command::new("git") - .args(["init"]) - .current_dir(temp_path) - .output() - .expect("Failed to initialize git repo"); - - // Change to the temp directory for the test - let original_dir = std::env::current_dir().expect("Failed to get current dir"); - std::env::set_current_dir(temp_path).expect("Failed to change directory"); - - // Create a temporary database - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let cmd = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: Some("test_project".to_string()), - mix_env: Some("test".to_string()), - }; - - let result = cmd.execute(&db).expect("Setup with hooks should succeed"); - - // Verify hook file exists and is executable BEFORE restoring directory - let hook_path = temp_path.join(".git").join("hooks").join("post-commit"); - assert!(hook_path.exists(), "Hook file should exist"); - - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - let metadata = fs::metadata(&hook_path).expect("Failed to get hook metadata"); - let permissions = metadata.permissions(); - assert!( - permissions.mode() & 0o111 != 0, - "Hook should be executable" - ); - } - - // Verify hook content - let hook_content = fs::read_to_string(&hook_path).expect("Failed to read hook"); - assert!(hook_content.contains("#!/usr/bin/env bash")); - assert!(hook_content.contains("ex_ast --git-diff")); - assert!(hook_content.contains("code_search")); - assert!(hook_content.contains("GIT_REF")); // Uses variable for git reference - - // Verify hooks were installed - assert!(result.hooks.is_some()); - let hooks = result.hooks.unwrap(); - - // Should have installed 1 hook (post-commit) - assert_eq!(hooks.hooks_installed, 1); - assert_eq!(hooks.hooks_skipped, 0); - assert_eq!(hooks.hooks_overwritten, 0); - - // Should have 1 hook file - assert_eq!(hooks.hooks.len(), 1); - assert_eq!(hooks.hooks[0].path, "post-commit"); - assert!(matches!(hooks.hooks[0].status, TemplateFileState::Installed)); - - // Should have configured 2 git settings (project-name and mix-env) - assert_eq!(hooks.git_config.len(), 2); - - // Verify git config values - let project_config = hooks.git_config.iter().find(|c| c.key == "code-search.project-name"); - assert!(project_config.is_some()); - assert_eq!(project_config.unwrap().value, "test_project"); - assert!(project_config.unwrap().set); - - let mix_env_config = hooks.git_config.iter().find(|c| c.key == "code-search.mix-env"); - assert!(mix_env_config.is_some()); - assert_eq!(mix_env_config.unwrap().value, "test"); - assert!(mix_env_config.unwrap().set); - - // Restore original directory - std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted - } - - #[test] - #[serial_test::serial] - fn test_install_hooks_with_defaults() { - use std::process::Command; - use tempfile::TempDir; - - // Create a temporary directory and initialize a git repo - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let temp_path = temp_dir.path(); - - Command::new("git") - .args(["init"]) - .current_dir(temp_path) - .output() - .expect("Failed to initialize git repo"); - - let original_dir = std::env::current_dir().expect("Failed to get current dir"); - std::env::set_current_dir(temp_path).expect("Failed to change directory"); - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let cmd = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - let result = cmd.execute(&db).expect("Setup with hooks should succeed"); - - assert!(result.hooks.is_some()); - let hooks = result.hooks.unwrap(); - - // Should only set mix-env (project-name not set when None) - assert_eq!(hooks.git_config.len(), 1); - - // Verify default values were used - let mix_env_config = hooks.git_config.iter().find(|c| c.key == "code-search.mix-env"); - assert!(mix_env_config.is_some()); - assert_eq!(mix_env_config.unwrap().value, "dev"); - - // Verify project-name was NOT set - let project_config = hooks.git_config.iter().find(|c| c.key == "code-search.project-name"); - assert!(project_config.is_none()); - - // Restore original directory - std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted - } - - #[test] - #[serial_test::serial] - fn test_install_hooks_skips_existing() { - use std::process::Command; - use tempfile::TempDir; - - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let temp_path = temp_dir.path(); - - Command::new("git") - .args(["init"]) - .current_dir(temp_path) - .output() - .expect("Failed to initialize git repo"); - - let original_dir = std::env::current_dir().expect("Failed to get current dir"); - std::env::set_current_dir(temp_path).expect("Failed to change directory"); - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - // First installation - let cmd1 = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - let result1 = cmd1.execute(&db).expect("First install should succeed"); - assert_eq!(result1.hooks.as_ref().unwrap().hooks_installed, 1); - - // Second installation without force - let cmd2 = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - let result2 = cmd2.execute(&db).expect("Second install should succeed"); - - // Should skip existing hook - assert_eq!(result2.hooks.as_ref().unwrap().hooks_installed, 0); - assert_eq!(result2.hooks.as_ref().unwrap().hooks_skipped, 1); - assert_eq!(result2.hooks.as_ref().unwrap().hooks_overwritten, 0); - - // Restore original directory - std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted - } - - #[test] - #[serial_test::serial] - fn test_install_hooks_force_overwrites() { - use std::process::Command; - use tempfile::TempDir; - - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let temp_path = temp_dir.path(); - - Command::new("git") - .args(["init"]) - .current_dir(temp_path) - .output() - .expect("Failed to initialize git repo"); - - let original_dir = std::env::current_dir().expect("Failed to get current dir"); - std::env::set_current_dir(temp_path).expect("Failed to change directory"); - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - // First installation - let cmd1 = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - cmd1.execute(&db).expect("First install should succeed"); - - // Second installation with force - let cmd2 = SetupCmd { - force: true, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - let result2 = cmd2.execute(&db).expect("Second install with force should succeed"); - - // Should overwrite existing hook - assert_eq!(result2.hooks.as_ref().unwrap().hooks_installed, 0); - assert_eq!(result2.hooks.as_ref().unwrap().hooks_skipped, 0); - assert_eq!(result2.hooks.as_ref().unwrap().hooks_overwritten, 1); - - // Restore original directory - std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted - } - - #[test] - #[serial_test::serial] - fn test_install_hooks_fails_outside_git_repo() { - use tempfile::TempDir; - - let temp_dir = TempDir::new().expect("Failed to create temp dir"); - let temp_path = temp_dir.path(); - - let original_dir = std::env::current_dir().expect("Failed to get current dir"); - std::env::set_current_dir(temp_path).expect("Failed to change directory"); - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let cmd = SetupCmd { - force: false, - dry_run: false, - install_skills: false, - install_hooks: true, - project_name: None, - mix_env: None, - }; - - let result = cmd.execute(&db); - - // Restore original directory - std::env::set_current_dir(&original_dir).ok(); // Ignore error if original_dir was deleted - - // Should fail because we're not in a git repo - assert!(result.is_err()); - let err_msg = result.unwrap_err().to_string(); - assert!(err_msg.contains("Not in a git repository")); - } -} diff --git a/src/commands/setup/mod.rs b/src/commands/setup/mod.rs deleted file mode 100644 index 463dac9..0000000 --- a/src/commands/setup/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -mod execute; -mod output; - -use std::error::Error; -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Create database schema without importing data -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search setup # Create schema in .code_search/cozo.sqlite - code_search setup --force # Overwrite existing templates/hooks - code_search setup --dry-run # Show what would be created - code_search setup --install-skills # Create schema and install skill templates - code_search setup --install-skills --force # Overwrite existing skill files - code_search setup --install-hooks # Install git hooks for incremental updates - code_search setup --install-hooks --project-name my_app # Configure project name - code_search setup --install-skills --install-hooks # Install both skills and hooks")] -pub struct SetupCmd { - /// Overwrite existing template and hook files (does not affect schema) - #[arg(long, default_value_t = false)] - pub force: bool, - - /// Show what would be created without doing it - #[arg(long, default_value_t = false)] - pub dry_run: bool, - - /// Install skill templates to .claude/skills/ - #[arg(long, default_value_t = false)] - pub install_skills: bool, - - /// Install git hooks for incremental database updates - #[arg(long, default_value_t = false)] - pub install_hooks: bool, - - /// Project name to configure in git hooks (only used with --install-hooks) - #[arg(long)] - pub project_name: Option, - - /// Mix environment to configure in git hooks (defaults to 'dev', only used with --install-hooks) - #[arg(long)] - pub mix_env: Option, -} - -impl CommandRunner for SetupCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/setup/output.rs b/src/commands/setup/output.rs deleted file mode 100644 index 3a588d8..0000000 --- a/src/commands/setup/output.rs +++ /dev/null @@ -1,189 +0,0 @@ -//! Output formatting for setup command results. - -use crate::output::Outputable; -use crate::commands::setup::execute::{SetupResult, RelationState, TemplateFileState}; - -impl Outputable for SetupResult { - fn to_table(&self) -> String { - let mut output = String::new(); - - output.push_str("Database Setup\n\n"); - - if self.dry_run { - output.push_str("Schema creation (dry-run):\n"); - } else { - output.push_str("Schema creation:\n"); - } - - for relation in &self.relations { - let symbol = match relation.status { - RelationState::Created => "✓", - RelationState::AlreadyExists => "✓", - RelationState::WouldCreate => "→", - }; - - let status_text = match relation.status { - RelationState::Created => "created", - RelationState::AlreadyExists => "exists", - RelationState::WouldCreate => "would create", - }; - - output.push_str(&format!(" {} {} ({})\n", symbol, relation.name, status_text)); - } - - if self.dry_run { - output.push_str("\nNo changes made (dry-run mode).\n"); - } else if self.created_new { - output.push_str("\nDatabase ready.\n"); - } else { - output.push_str("\nDatabase already configured.\n"); - } - - // Add template installation results if present - if let Some(ref templates) = self.templates { - output.push_str("\nTemplates Installation:\n"); - - // Skills summary - let total_skills = templates.skills_installed + templates.skills_skipped + templates.skills_overwritten; - if total_skills > 0 { - output.push_str("\n Skills:\n"); - output.push_str(&format!( - " Installed: {}, Skipped: {}, Overwritten: {}\n", - templates.skills_installed, templates.skills_skipped, templates.skills_overwritten - )); - - // Group skill files by status - let installed: Vec<_> = templates - .skills - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Installed)) - .collect(); - let overwritten: Vec<_> = templates - .skills - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) - .collect(); - let _skipped: Vec<_> = templates - .skills - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Skipped)) - .collect(); - - // Show installed skills (only first few) - if !installed.is_empty() { - let show_count = installed.len().min(5); - for file in &installed[..show_count] { - output.push_str(&format!(" ✓ {}\n", file.path)); - } - if installed.len() > show_count { - output.push_str(&format!(" ... and {} more\n", installed.len() - show_count)); - } - } - - // Show overwritten skills - if !overwritten.is_empty() { - let show_count = overwritten.len().min(3); - for file in &overwritten[..show_count] { - output.push_str(&format!(" ⟳ {}\n", file.path)); - } - if overwritten.len() > show_count { - output.push_str(&format!(" ... and {} more overwritten\n", overwritten.len() - show_count)); - } - } - } - - // Agents summary - let total_agents = templates.agents_installed + templates.agents_skipped + templates.agents_overwritten; - if total_agents > 0 { - output.push_str("\n Agents:\n"); - output.push_str(&format!( - " Installed: {}, Skipped: {}, Overwritten: {}\n", - templates.agents_installed, templates.agents_skipped, templates.agents_overwritten - )); - - // Group agent files by status - let installed: Vec<_> = templates - .agents - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Installed)) - .collect(); - let overwritten: Vec<_> = templates - .agents - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) - .collect(); - - // Show installed agents - if !installed.is_empty() { - for file in installed { - output.push_str(&format!(" ✓ {}\n", file.path)); - } - } - - // Show overwritten agents - if !overwritten.is_empty() { - for file in overwritten { - output.push_str(&format!(" ⟳ {}\n", file.path)); - } - } - } - - output.push_str("\nTemplates installed to .claude/\n"); - } - - // Add git hooks installation results if present - if let Some(ref hooks) = self.hooks { - output.push_str("\nGit Hooks Installation:\n"); - - // Hooks summary - let total_hooks = hooks.hooks_installed + hooks.hooks_skipped + hooks.hooks_overwritten; - if total_hooks > 0 { - output.push_str(&format!( - "\n Installed: {}, Skipped: {}, Overwritten: {}\n", - hooks.hooks_installed, hooks.hooks_skipped, hooks.hooks_overwritten - )); - - // Show hooks by status - let installed: Vec<_> = hooks - .hooks - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Installed)) - .collect(); - let overwritten: Vec<_> = hooks - .hooks - .iter() - .filter(|f| matches!(f.status, TemplateFileState::Overwritten)) - .collect(); - - if !installed.is_empty() { - for file in installed { - output.push_str(&format!(" ✓ {}\n", file.path)); - } - } - - if !overwritten.is_empty() { - for file in overwritten { - output.push_str(&format!(" ⟳ {}\n", file.path)); - } - } - } - - // Git config - if !hooks.git_config.is_empty() { - output.push_str("\n Git Configuration:\n"); - for config in &hooks.git_config { - let symbol = if config.set { "✓" } else { "✗" }; - output.push_str(&format!( - " {} {} = {}\n", - symbol, config.key, config.value - )); - } - } - - output.push_str("\nGit hooks installed to .git/hooks/\n"); - output.push_str("Run 'git config --get-regexp code-search' to view configuration.\n"); - } - - output - } -} diff --git a/src/commands/struct_usage/cli_tests.rs b/src/commands/struct_usage/cli_tests.rs deleted file mode 100644 index 87d0eda..0000000 --- a/src/commands/struct_usage/cli_tests.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! CLI parsing tests for struct-usage command. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "struct-usage", - test_name: test_requires_pattern, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_with_pattern, - args: ["User.t"], - field: pattern, - expected: "User.t", - } - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_with_module, - args: ["User.t", "MyApp.Accounts"], - field: module, - expected: Some("MyApp.Accounts".to_string()), - } - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_with_by_module, - args: ["User.t", "--by-module"], - field: by_module, - expected: true, - } - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_by_module_default_false, - args: ["User.t"], - field: by_module, - expected: false, - } - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_with_regex, - args: [".*\\.t", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "struct-usage", - variant: StructUsage, - test_name: test_with_limit, - args: ["User.t", "--limit", "50"], - field: common.limit, - expected: 50, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "struct-usage", - variant: StructUsage, - required_args: ["User.t"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } -} diff --git a/src/commands/struct_usage/execute.rs b/src/commands/struct_usage/execute.rs deleted file mode 100644 index 6175720..0000000 --- a/src/commands/struct_usage/execute.rs +++ /dev/null @@ -1,177 +0,0 @@ -use std::collections::{BTreeMap, HashSet}; -use std::error::Error; - -use serde::Serialize; - -use super::StructUsageCmd; -use crate::commands::Execute; -use crate::queries::struct_usage::{find_struct_usage, StructUsageEntry}; -use crate::types::ModuleGroupResult; - -/// A function that uses a struct type -#[derive(Debug, Clone, Serialize)] -pub struct UsageInfo { - pub name: String, - pub arity: i64, - pub inputs: String, - pub returns: String, - pub line: i64, -} - -/// A module and its usage counts for a struct type -#[derive(Debug, Clone, Serialize)] -pub struct ModuleStructUsage { - pub name: String, - pub accepts_count: i64, - pub returns_count: i64, - pub total: i64, -} - -/// Result containing aggregated module-level struct usage -#[derive(Debug, Clone, Serialize)] -pub struct StructModulesResult { - pub struct_pattern: String, - pub total_modules: usize, - pub total_functions: usize, - pub modules: Vec, -} - -/// Output type that can be either detailed or aggregated -#[derive(Debug, Serialize)] -#[serde(untagged)] -pub enum StructUsageOutput { - Detailed(ModuleGroupResult), - ByModule(StructModulesResult), -} - -impl ModuleGroupResult { - /// Build grouped result from flat StructUsageEntry list - fn from_entries( - pattern: String, - module_filter: Option, - entries: Vec, - ) -> Self { - let total_items = entries.len(); - - // Use helper to group by module - let items = crate::utils::group_by_module(entries, |entry| { - let usage_info = UsageInfo { - name: entry.name, - arity: entry.arity, - inputs: entry.inputs_string, - returns: entry.return_string, - line: entry.line, - }; - (entry.module, usage_info) - }); - - ModuleGroupResult { - module_pattern: module_filter.unwrap_or_else(|| "*".to_string()), - function_pattern: Some(pattern), - total_items, - items, - } - } -} - -impl StructModulesResult { - /// Build aggregated result from flat StructUsageEntry list - fn from_entries(pattern: String, entries: Vec) -> Self { - // Aggregate by module, tracking which functions accept vs return - let mut module_map: BTreeMap> = BTreeMap::new(); - let mut module_accepts: BTreeMap> = BTreeMap::new(); - let mut module_returns: BTreeMap> = BTreeMap::new(); - - for entry in &entries { - // Track unique functions per module - module_map - .entry(entry.module.clone()) - .or_default() - .insert(format!("{}/{}", entry.name, entry.arity)); - - // Check if function accepts the type - if entry.inputs_string.contains(&pattern) { - module_accepts - .entry(entry.module.clone()) - .or_default() - .insert(format!("{}/{}", entry.name, entry.arity)); - } - - // Check if function returns the type - if entry.return_string.contains(&pattern) { - module_returns - .entry(entry.module.clone()) - .or_default() - .insert(format!("{}/{}", entry.name, entry.arity)); - } - } - - // Convert to result type, sorted by total count descending - let mut modules: Vec = module_map - .into_iter() - .map(|(name, functions)| { - let accepts_count = module_accepts - .get(&name) - .map(|s| s.len() as i64) - .unwrap_or(0); - let returns_count = module_returns - .get(&name) - .map(|s| s.len() as i64) - .unwrap_or(0); - let total = functions.len() as i64; - - ModuleStructUsage { - name, - accepts_count, - returns_count, - total, - } - }) - .collect(); - - // Sort by total count descending, then by module name - modules.sort_by(|a, b| { - let cmp = b.total.cmp(&a.total); - if cmp == std::cmp::Ordering::Equal { - a.name.cmp(&b.name) - } else { - cmp - } - }); - - let total_modules = modules.len(); - let total_functions = entries.len(); - - StructModulesResult { - struct_pattern: pattern, - total_modules, - total_functions, - modules, - } - } -} - -impl Execute for StructUsageCmd { - type Output = StructUsageOutput; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let entries = find_struct_usage( - db, - &self.pattern, - &self.common.project, - self.common.regex, - self.module.as_deref(), - self.common.limit, - )?; - - if self.by_module { - Ok(StructUsageOutput::ByModule( - StructModulesResult::from_entries(self.pattern, entries), - )) - } else { - Ok(StructUsageOutput::Detailed( - ModuleGroupResult::::from_entries(self.pattern, self.module, entries), - )) - } - } -} diff --git a/src/commands/struct_usage/execute_tests.rs b/src/commands/struct_usage/execute_tests.rs deleted file mode 100644 index 9874cc1..0000000 --- a/src/commands/struct_usage/execute_tests.rs +++ /dev/null @@ -1,228 +0,0 @@ -//! Execute tests for struct-usage command. - -#[cfg(test)] -mod tests { - use super::super::StructUsageCmd; - use super::super::execute::StructUsageOutput; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: type_signatures, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - Detailed mode - // ========================================================================= - - // The type_signatures fixture has User.t() in returns for: - // - MyApp.Accounts: get_user/1, get_user/2, list_users/0, create_user/1 - // - MyApp.Users: get_by_email/1, authenticate/2 - crate::execute_test! { - test_name: test_struct_usage_finds_user_type, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "User.t".to_string(), - module: None, - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::Detailed(ref detail) => { - assert!(detail.total_items > 0, "Should find functions using User.t"); - // Should have entries from at least 2 modules - assert!(detail.items.len() >= 2, "Should find User.t in multiple modules"); - } - _ => panic!("Expected Detailed output"), - } - }, - } - - crate::execute_test! { - test_name: test_struct_usage_with_module_filter, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "User.t".to_string(), - module: Some("MyApp.Accounts".to_string()), - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::Detailed(ref detail) => { - assert!(detail.total_items > 0, "Should find functions in MyApp.Accounts"); - // All results should be from MyApp.Accounts - for module_group in &detail.items { - assert_eq!(module_group.name, "MyApp.Accounts"); - } - } - _ => panic!("Expected Detailed output"), - } - }, - } - - // ========================================================================= - // Core functionality tests - ByModule mode - // ========================================================================= - - crate::execute_test! { - test_name: test_struct_usage_by_module, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "User.t".to_string(), - module: None, - by_module: true, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::ByModule(ref by_module) => { - assert!(by_module.total_modules > 0, "Should find modules using User.t"); - assert!(by_module.total_functions > 0, "Should have function count"); - // Each module should have counts - for module in &by_module.modules { - assert!(module.total > 0, "Module should have at least one function"); - } - } - _ => panic!("Expected ByModule output"), - } - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_test! { - test_name: test_struct_usage_no_match, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "NonExistentType.t".to_string(), - module: None, - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::Detailed(ref detail) => { - assert!(detail.items.is_empty(), "Should find no matches"); - assert_eq!(detail.total_items, 0); - } - _ => panic!("Expected Detailed output"), - } - }, - } - - crate::execute_test! { - test_name: test_struct_usage_by_module_no_match, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "NonExistentType.t".to_string(), - module: None, - by_module: true, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::ByModule(ref by_module) => { - assert!(by_module.modules.is_empty(), "Should find no modules"); - assert_eq!(by_module.total_modules, 0); - assert_eq!(by_module.total_functions, 0); - } - _ => panic!("Expected ByModule output"), - } - }, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_struct_usage_with_limit, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: "User.t".to_string(), - module: None, - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 1, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::Detailed(ref detail) => { - assert_eq!(detail.total_items, 1, "Limit should restrict to 1 result"); - } - _ => panic!("Expected Detailed output"), - } - }, - } - - crate::execute_test! { - test_name: test_struct_usage_regex_pattern, - fixture: populated_db, - cmd: StructUsageCmd { - pattern: ".*\\.t\\(\\)".to_string(), - module: None, - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - match result { - StructUsageOutput::Detailed(ref detail) => { - // Should match User.t(), Ecto.Changeset.t(), etc. - assert!(detail.total_items > 0, "Regex should match .t() types"); - } - _ => panic!("Expected Detailed output"), - } - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: StructUsageCmd, - cmd: StructUsageCmd { - pattern: "User.t".to_string(), - module: None, - by_module: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/struct_usage/mod.rs b/src/commands/struct_usage/mod.rs deleted file mode 100644 index a1c4f13..0000000 --- a/src/commands/struct_usage/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -mod execute; -mod output; - -#[cfg(test)] -mod cli_tests; -#[cfg(test)] -mod execute_tests; -#[cfg(test)] -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions that accept or return a specific type pattern -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search struct-usage \"User.t\" # Find functions using User.t - code_search struct-usage \"Changeset.t\" # Find functions using Changeset.t - code_search struct-usage \"User.t\" MyApp # Filter to module MyApp - code_search struct-usage \"User.t\" --by-module # Summarize by module - code_search struct-usage -r \".*\\.t\" # Regex pattern matching -")] -pub struct StructUsageCmd { - /// Type pattern to search for in both inputs and returns - pub pattern: String, - - /// Module filter pattern - pub module: Option, - - /// Aggregate results by module (show counts instead of function details) - #[arg(long)] - pub by_module: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for StructUsageCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/struct_usage/output.rs b/src/commands/struct_usage/output.rs deleted file mode 100644 index a430ee2..0000000 --- a/src/commands/struct_usage/output.rs +++ /dev/null @@ -1,140 +0,0 @@ -//! Output formatting for struct-usage command results. - -use regex::Regex; -use std::sync::LazyLock; - -use crate::output::{Outputable, TableFormatter}; -use crate::types::ModuleGroupResult; -use super::execute::{UsageInfo, StructUsageOutput, StructModulesResult}; - -/// Regex to match Elixir struct maps like `%{__struct__: Module.Name, field: type(), ...}` -static STRUCT_MAP_REGEX: LazyLock = LazyLock::new(|| { - Regex::new(r"%\{__struct__:\s*([A-Za-z][A-Za-z0-9_.]*),\s*[^}]+\}").unwrap() -}); - -/// Simplify struct representations in type strings. -/// Converts `%{__struct__: Module.Name, field: type(), ...}` to `%Module.Name{}` -fn simplify_structs(s: &str) -> String { - STRUCT_MAP_REGEX.replace_all(s, "%$1{}").to_string() -} - -impl TableFormatter for ModuleGroupResult { - type Entry = UsageInfo; - - fn format_header(&self) -> String { - let pattern = self.function_pattern.as_ref().map(|s| s.as_str()).unwrap_or("*"); - format!("Functions using \"{}\"", pattern) - } - - fn format_empty_message(&self) -> String { - "No functions found.".to_string() - } - - fn format_summary(&self, total: usize, module_count: usize) -> String { - format!("Found {} function(s) in {} module(s):", total, module_count) - } - - fn format_module_header(&self, module_name: &str, _module_file: &str) -> String { - format!("{}:", module_name) - } - - fn format_entry(&self, usage_info: &UsageInfo, _module: &str, _file: &str) -> String { - format!( - "{}/{} accepts: {} returns: {}", - usage_info.name, - usage_info.arity, - simplify_structs(&usage_info.inputs), - simplify_structs(&usage_info.returns) - ) - } -} - -impl Outputable for StructModulesResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - // Header - lines.push(format!("Modules using \"{}\"", self.struct_pattern)); - lines.push(String::new()); - - if self.modules.is_empty() { - lines.push("No modules found.".to_string()); - return lines.join("\n"); - } - - // Summary - lines.push(format!( - "Found {} module(s) ({} function(s)):", - self.total_modules, self.total_functions - )); - lines.push(String::new()); - - // Table header - lines.push("Module Accepts Returns Total".to_string()); - lines.push("──────────────────────────────────────────────────".to_string()); - - // Table rows - for module in &self.modules { - let line = format!( - "{:<28} {:>7} {:>8} {:>5}", - truncate_module_name(&module.name, 28), - module.accepts_count, - module.returns_count, - module.total - ); - lines.push(line); - } - - lines.join("\n") - } -} - -/// Truncate module name to max width with ellipsis if needed -fn truncate_module_name(name: &str, max_width: usize) -> String { - if name.len() > max_width { - format!("{}…", &name[..max_width - 1]) - } else { - name.to_string() - } -} - -impl Outputable for StructUsageOutput { - fn to_table(&self) -> String { - match self { - StructUsageOutput::Detailed(result) => result.to_table(), - StructUsageOutput::ByModule(result) => result.to_table(), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_simplify_structs_basic() { - let input = "%{__struct__: TradeGym.User, name: binary(), age: integer()}"; - let expected = "%TradeGym.User{}"; - assert_eq!(simplify_structs(input), expected); - } - - #[test] - fn test_simplify_structs_with_meta() { - let input = "%{__struct__: TradeGym.Repo.Schemas.User, __meta__: term(), name: binary()}"; - let expected = "%TradeGym.Repo.Schemas.User{}"; - assert_eq!(simplify_structs(input), expected); - } - - #[test] - fn test_simplify_structs_multiple() { - let input = "%{__struct__: Foo.Bar, x: 1} | %{__struct__: Baz.Qux, y: 2}"; - let expected = "%Foo.Bar{} | %Baz.Qux{}"; - assert_eq!(simplify_structs(input), expected); - } - - #[test] - fn test_simplify_structs_no_match() { - let input = "integer() | binary()"; - assert_eq!(simplify_structs(input), input); - } -} diff --git a/src/commands/struct_usage/output_tests.rs b/src/commands/struct_usage/output_tests.rs deleted file mode 100644 index 715ae09..0000000 --- a/src/commands/struct_usage/output_tests.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! Output formatting tests for struct-usage command. - -#[cfg(test)] -mod tests { - use super::super::execute::{ModuleStructUsage, StructModulesResult, StructUsageOutput, UsageInfo}; - use crate::types::{ModuleGroup, ModuleGroupResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - Detailed mode - // ========================================================================= - - const EMPTY_DETAILED_TABLE: &str = "\ -Functions using \"User.t\" - -No functions found."; - - const SINGLE_DETAILED_TABLE: &str = "\ -Functions using \"User.t\" - -Found 1 function(s) in 1 module(s): - -MyApp.Accounts: - get_user/1 accepts: integer() returns: %User{}"; - - // ========================================================================= - // Expected outputs - ByModule mode - // ========================================================================= - - const EMPTY_BY_MODULE_TABLE: &str = "\ -Modules using \"User.t\" - -No modules found."; - - const SINGLE_BY_MODULE_TABLE: &str = "\ -Modules using \"User.t\" - -Found 1 module(s) (2 function(s)): - -Module Accepts Returns Total -────────────────────────────────────────────────── -MyApp.Accounts 1 2 2"; - - // ========================================================================= - // Fixtures - Detailed mode - // ========================================================================= - - #[fixture] - fn empty_detailed() -> StructUsageOutput { - StructUsageOutput::Detailed(ModuleGroupResult { - module_pattern: "*".to_string(), - function_pattern: Some("User.t".to_string()), - total_items: 0, - items: vec![], - }) - } - - #[fixture] - fn single_detailed() -> StructUsageOutput { - StructUsageOutput::Detailed(ModuleGroupResult { - module_pattern: "*".to_string(), - function_pattern: Some("User.t".to_string()), - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: "lib/my_app/accounts.ex".to_string(), - function_count: Some(1), - entries: vec![UsageInfo { - name: "get_user".to_string(), - arity: 1, - inputs: "integer()".to_string(), - returns: "%{__struct__: User, id: integer()}".to_string(), - line: 10, - }], - }], - }) - } - - // ========================================================================= - // Fixtures - ByModule mode - // ========================================================================= - - #[fixture] - fn empty_by_module() -> StructUsageOutput { - StructUsageOutput::ByModule(StructModulesResult { - struct_pattern: "User.t".to_string(), - total_modules: 0, - total_functions: 0, - modules: vec![], - }) - } - - #[fixture] - fn single_by_module() -> StructUsageOutput { - StructUsageOutput::ByModule(StructModulesResult { - struct_pattern: "User.t".to_string(), - total_modules: 1, - total_functions: 2, - modules: vec![ModuleStructUsage { - name: "MyApp.Accounts".to_string(), - accepts_count: 1, - returns_count: 2, - total: 2, - }], - }) - } - - // ========================================================================= - // Tests - Detailed mode - // ========================================================================= - - crate::output_table_test! { - test_name: test_detailed_empty, - fixture: empty_detailed, - fixture_type: StructUsageOutput, - expected: EMPTY_DETAILED_TABLE, - } - - crate::output_table_test! { - test_name: test_detailed_single, - fixture: single_detailed, - fixture_type: StructUsageOutput, - expected: SINGLE_DETAILED_TABLE, - } - - // ========================================================================= - // Tests - ByModule mode - // ========================================================================= - - crate::output_table_test! { - test_name: test_by_module_empty, - fixture: empty_by_module, - fixture_type: StructUsageOutput, - expected: EMPTY_BY_MODULE_TABLE, - } - - crate::output_table_test! { - test_name: test_by_module_single, - fixture: single_by_module, - fixture_type: StructUsageOutput, - expected: SINGLE_BY_MODULE_TABLE, - } - - // ========================================================================= - // JSON format tests - // ========================================================================= - - #[rstest] - fn test_detailed_json(single_detailed: StructUsageOutput) { - use crate::output::{OutputFormat, Outputable}; - let output = single_detailed.format(OutputFormat::Json); - let parsed: serde_json::Value = - serde_json::from_str(&output).expect("Should produce valid JSON"); - - // Verify structure - assert!(parsed["items"].is_array()); - assert_eq!(parsed["total_items"], 1); - } - - #[rstest] - fn test_by_module_json(single_by_module: StructUsageOutput) { - use crate::output::{OutputFormat, Outputable}; - let output = single_by_module.format(OutputFormat::Json); - let parsed: serde_json::Value = - serde_json::from_str(&output).expect("Should produce valid JSON"); - - // Verify structure - assert!(parsed["modules"].is_array()); - assert_eq!(parsed["total_modules"], 1); - assert_eq!(parsed["total_functions"], 2); - } -} diff --git a/src/commands/trace/cli_tests.rs b/src/commands/trace/cli_tests.rs deleted file mode 100644 index 58f74f4..0000000 --- a/src/commands/trace/cli_tests.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! CLI parsing tests for trace command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Required argument tests - // ========================================================================= - - crate::cli_required_arg_test! { - command: "trace", - test_name: test_requires_module, - required_arg: "", - } - - crate::cli_required_arg_test! { - command: "trace", - test_name: test_requires_function, - required_arg: "", - } - - // ========================================================================= - // Option tests - // ========================================================================= - - crate::cli_option_test! { - command: "trace", - variant: Trace, - test_name: test_with_module_and_function, - args: ["MyApp.Accounts", "get_user"], - field: module, - expected: "MyApp.Accounts", - } - - crate::cli_option_test! { - command: "trace", - variant: Trace, - test_name: test_function_name, - args: ["MyApp.Accounts", "get_user"], - field: function, - expected: "get_user", - } - - crate::cli_option_test! { - command: "trace", - variant: Trace, - test_name: test_with_project, - args: ["MyApp", "foo", "--project", "my_custom_project"], - field: common.project, - expected: "my_custom_project", - } - - crate::cli_option_test! { - command: "trace", - variant: Trace, - test_name: test_with_depth, - args: ["MyApp", "foo", "--depth", "10"], - field: depth, - expected: 10, - } - - crate::cli_option_test! { - command: "trace", - variant: Trace, - test_name: test_with_limit, - args: ["MyApp", "foo", "--limit", "50"], - field: common.limit, - expected: 50, - } - - // ========================================================================= - // Limit validation tests - // ========================================================================= - - crate::cli_limit_tests! { - command: "trace", - variant: Trace, - required_args: ["MyApp", "foo"], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Edge case tests (depth validation - different from standard limit) - // ========================================================================= - - #[rstest] - fn test_depth_default() { - let args = Args::try_parse_from(["code_search", "trace", "MyApp", "foo"]).unwrap(); - match args.command { - crate::commands::Command::Trace(cmd) => { - assert_eq!(cmd.depth, 5); - } - _ => panic!("Expected Trace command"), - } - } - - #[rstest] - fn test_depth_zero_rejected() { - let result = - Args::try_parse_from(["code_search", "trace", "MyApp", "foo", "--depth", "0"]); - assert!(result.is_err()); - } - - #[rstest] - fn test_depth_exceeds_max_rejected() { - let result = - Args::try_parse_from(["code_search", "trace", "MyApp", "foo", "--depth", "21"]); - assert!(result.is_err()); - } -} diff --git a/src/commands/trace/execute.rs b/src/commands/trace/execute.rs deleted file mode 100644 index 7d560bb..0000000 --- a/src/commands/trace/execute.rs +++ /dev/null @@ -1,179 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; - -use super::TraceCmd; -use crate::commands::Execute; -use crate::queries::trace::trace_calls; -use crate::types::{Call, TraceDirection, TraceEntry, TraceResult}; - -impl TraceResult { - /// Build a flattened trace from Call objects - pub fn from_calls( - start_module: String, - start_function: String, - max_depth: u32, - calls: Vec, - ) -> Self { - let mut entries = Vec::new(); - let mut entry_index_map: HashMap<(String, String, i64, i64), usize> = HashMap::new(); - - // Add the starting function as the root entry at depth 0 - entries.push(TraceEntry { - module: start_module.clone(), - function: start_function.clone(), - arity: 0, // Will be updated from first call if available - kind: String::new(), - start_line: 0, - end_line: 0, - file: String::new(), - depth: 0, - line: 0, - parent_index: None, - }); - entry_index_map.insert((start_module.clone(), start_function.clone(), 0, 0), 0); - - if calls.is_empty() { - return Self::empty(start_module, start_function, max_depth, TraceDirection::Forward); - } - - // Group calls by depth, consuming the Vec to take ownership - let mut by_depth: HashMap> = HashMap::new(); - for call in calls { - if let Some(depth) = call.depth { - by_depth.entry(depth).or_default().push(call); - } - } - - // Process depth 1 (direct callees from start function) - if let Some(depth1_calls) = by_depth.remove(&1) { - // Track seen entries by index into entries vec (avoids storing strings) - let mut seen_at_depth: std::collections::HashSet = std::collections::HashSet::new(); - - for call in depth1_calls { - // Check if we already have this callee at this depth - let existing = entries.iter().position(|e| { - e.depth == 1 - && e.module == call.callee.module.as_ref() - && e.function == call.callee.name.as_ref() - && e.arity == call.callee.arity - }); - - if existing.is_none() || seen_at_depth.insert(existing.unwrap_or(usize::MAX)) { - if existing.is_none() { - let entry_idx = entries.len(); - // Convert from Rc to String for storage - let module = call.callee.module.to_string(); - let function = call.callee.name.to_string(); - let arity = call.callee.arity; - entry_index_map.insert((module.clone(), function.clone(), arity, 1i64), entry_idx); - entries.push(TraceEntry { - module, - function, - arity, - kind: call.callee.kind.as_deref().unwrap_or("").to_string(), - start_line: call.callee.start_line.unwrap_or(0), - end_line: call.callee.end_line.unwrap_or(0), - file: call.callee.file.as_deref().unwrap_or("").to_string(), - depth: 1, - line: call.line, - parent_index: Some(0), - }); - } - } - } - } - - // Process deeper levels - for depth in 2..=max_depth as i64 { - if let Some(depth_calls) = by_depth.remove(&depth) { - for call in depth_calls { - // Check if we already have this callee at this depth - let existing = entries.iter().position(|e| { - e.depth == depth - && e.module == call.callee.module.as_ref() - && e.function == call.callee.name.as_ref() - && e.arity == call.callee.arity - }); - - if existing.is_none() { - // Find parent index using references (no cloning) - let parent_index = entries.iter().position(|e| { - e.depth == depth - 1 - && e.module == call.caller.module.as_ref() - && e.function == call.caller.name.as_ref() - && e.arity == call.caller.arity - }); - - if parent_index.is_some() { - let entry_idx = entries.len(); - // Convert from Rc to String for storage - let module = call.callee.module.to_string(); - let function = call.callee.name.to_string(); - let arity = call.callee.arity; - entry_index_map.insert((module.clone(), function.clone(), arity, depth), entry_idx); - entries.push(TraceEntry { - module, - function, - arity, - kind: call.callee.kind.as_deref().unwrap_or("").to_string(), - start_line: call.callee.start_line.unwrap_or(0), - end_line: call.callee.end_line.unwrap_or(0), - file: call.callee.file.as_deref().unwrap_or("").to_string(), - depth, - line: call.line, - parent_index, - }); - } - } - } - } - } - - let total_items = entries.len() - 1; // Exclude the root entry from count - - Self { - module: start_module, - function: start_function, - max_depth, - direction: TraceDirection::Forward, - total_items, - entries, - } - } -} - -impl Execute for TraceCmd { - type Output = TraceResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let calls = trace_calls( - db, - &self.module, - &self.function, - self.arity, - &self.common.project, - self.common.regex, - self.depth, - self.common.limit, - )?; - - Ok(TraceResult::from_calls( - self.module, - self.function, - self.depth, - calls, - )) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_empty_trace() { - let result = TraceResult::from_calls("TestModule".to_string(), "test_func".to_string(), 5, vec![]); - assert_eq!(result.total_items, 0); - assert_eq!(result.entries.len(), 0); - } -} diff --git a/src/commands/trace/execute_tests.rs b/src/commands/trace/execute_tests.rs deleted file mode 100644 index ee7e69a..0000000 --- a/src/commands/trace/execute_tests.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! Execute tests for trace command. - -#[cfg(test)] -mod tests { - use super::super::TraceCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // Controller.index only calls Accounts.list_users at depth 1 - crate::execute_test! { - test_name: test_trace_single_depth, - fixture: populated_db, - cmd: TraceCmd { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: None, - depth: 1, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 1); - assert_eq!(result.entries.len(), 2); // Root + 1 callee - // Entry at index 0 is the root (Controller.index) - assert_eq!(result.entries[0].module, "MyApp.Controller"); - // Entry at index 1 is the callee (Accounts.list_users) - assert_eq!(result.entries[1].module, "MyApp.Accounts"); - assert_eq!(result.entries[1].function, "list_users"); - }, - } - - // Controller.index -> list_users -> all (2 steps with depth 2) - crate::execute_test! { - test_name: test_trace_multiple_depths, - fixture: populated_db, - cmd: TraceCmd { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: None, - depth: 3, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2); - }, - } - - crate::execute_test! { - test_name: test_trace_with_depth_limit, - fixture: populated_db, - cmd: TraceCmd { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: None, - depth: 2, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2); - assert!(result.max_depth <= 2); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_trace_no_match, - fixture: populated_db, - cmd: TraceCmd { - module: "NonExistent".to_string(), - function: "foo".to_string(), - arity: None, - depth: 5, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: entries, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: TraceCmd, - cmd: TraceCmd { - module: "MyApp".to_string(), - function: "foo".to_string(), - arity: None, - depth: 5, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/trace/mod.rs b/src/commands/trace/mod.rs deleted file mode 100644 index 06faf02..0000000 --- a/src/commands/trace/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Trace call chains from a starting function (forward traversal) -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search trace MyApp.Web index # Trace from controller action - code_search trace MyApp handle_call --depth 10 # Deeper traversal - code_search trace -r 'MyApp\\..*' 'handle_.*' # Regex pattern -")] -pub struct TraceCmd { - /// Starting module name (exact match or pattern with --regex) - pub module: String, - - /// Starting function name (exact match or pattern with --regex) - pub function: String, - - /// Function arity (optional) - #[arg(short, long)] - pub arity: Option, - - /// Maximum depth to traverse (1-20) - #[arg(long, default_value_t = 5, value_parser = clap::value_parser!(u32).range(1..=20))] - pub depth: u32, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for TraceCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/trace/output.rs b/src/commands/trace/output.rs deleted file mode 100644 index a09379d..0000000 --- a/src/commands/trace/output.rs +++ /dev/null @@ -1,179 +0,0 @@ -//! Output formatting for trace and reverse-trace command results. - -use crate::output::Outputable; -use crate::types::{TraceResult, TraceDirection}; - -impl Outputable for TraceResult { - fn to_table(&self) -> String { - match self.direction { - TraceDirection::Forward => format_trace(self), - TraceDirection::Backward => format_reverse_trace(self), - } - } -} - -/// Format a forward trace -fn format_trace(result: &TraceResult) -> String { - let mut lines = Vec::new(); - - let header = format!("Trace from: {}.{}", result.module, result.function); - lines.push(header); - lines.push(format!("Max depth: {}", result.max_depth)); - lines.push(String::new()); - - if result.entries.is_empty() { - lines.push("No calls found.".to_string()); - return lines.join("\n"); - } - - lines.push(format!("Found {} call(s) in chain:", result.total_items)); - lines.push(String::new()); - - // Find root entries (those with no parent) - for (idx, entry) in result.entries.iter().enumerate() { - if entry.parent_index.is_none() { - format_entry(&mut lines, &result.entries, idx, 0); - } - } - - lines.join("\n") -} - -/// Format a reverse trace -fn format_reverse_trace(result: &TraceResult) -> String { - let mut lines = Vec::new(); - - let header = format!("Reverse trace to: {}.{}", result.module, result.function); - lines.push(header); - lines.push(format!("Max depth: {}", result.max_depth)); - lines.push(String::new()); - - if result.entries.is_empty() { - lines.push("No callers found.".to_string()); - return lines.join("\n"); - } - - lines.push(format!("Found {} caller(s) in chain:", result.total_items)); - lines.push(String::new()); - - // Find root entries (those with no parent) - for (idx, entry) in result.entries.iter().enumerate() { - if entry.parent_index.is_none() { - format_reverse_entry(&mut lines, &result.entries, idx, 0); - } - } - - lines.join("\n") -} - -/// Format a reverse trace entry (callers going up the chain) -fn format_reverse_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { - let entry = &entries[idx]; - let indent = " ".repeat(depth); - let kind_str = if entry.kind.is_empty() { - String::new() - } else { - format!(" [{}]", entry.kind) - }; - - // Extract just the filename from path - let filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); - - // For root entries (no parent), show without prefix - if entry.parent_index.is_none() { - lines.push(format!( - "{}{}.{}/{}{} ({}:L{}:{})", - indent, entry.module, entry.function, entry.arity, kind_str, - filename, entry.start_line, entry.end_line - )); - } else { - // For child entries, show with arrow indicating "called by" relationship - lines.push(format!( - "{}← @ L{} {}.{}/{}{} ({}:L{}:{})", - indent, entry.line, entry.module, entry.function, entry.arity, kind_str, - filename, entry.start_line, entry.end_line - )); - } - - // Find children (additional callers going up the chain) - for (child_idx, child) in entries.iter().enumerate() { - if child.parent_index == Some(idx) { - format_reverse_entry(lines, entries, child_idx, depth + 1); - } - } -} - -/// Recursively format an entry and its children -fn format_entry(lines: &mut Vec, entries: &[crate::types::TraceEntry], idx: usize, depth: usize) { - let entry = &entries[idx]; - let indent = " ".repeat(depth); - let kind_str = if entry.kind.is_empty() { - String::new() - } else { - format!(" [{}]", entry.kind) - }; - - // Extract just the filename from path - let filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); - - lines.push(format!( - "{}{}.{}/{}{} ({}:L{}:{})", - indent, entry.module, entry.function, entry.arity, kind_str, - filename, entry.start_line, entry.end_line - )); - - // Find children of this entry - for (child_idx, child) in entries.iter().enumerate() { - if child.parent_index == Some(idx) { - format_call(lines, entries, child_idx, depth + 1, &entry.module, &entry.file); - } - } -} - -/// Format a child call/caller entry -fn format_call( - lines: &mut Vec, - entries: &[crate::types::TraceEntry], - idx: usize, - depth: usize, - parent_module: &str, - parent_file: &str, -) { - let entry = &entries[idx]; - let indent = " ".repeat(depth); - - // Show module only if different from parent - let name = if entry.module == parent_module { - format!("{}/{}", entry.function, entry.arity) - } else { - format!("{}.{}/{}", entry.module, entry.function, entry.arity) - }; - - let kind_str = if entry.kind.is_empty() { - String::new() - } else { - format!(" [{}]", entry.kind) - }; - - // Extract just the filename - let child_filename = entry.file.rsplit('/').next().unwrap_or(&entry.file); - let parent_filename = parent_file.rsplit('/').next().unwrap_or(parent_file); - - let location = if child_filename == parent_filename { - format!("L{}:{}", entry.start_line, entry.end_line) - } else { - format!("{}:L{}:{}", child_filename, entry.start_line, entry.end_line) - }; - - lines.push(format!( - "{}→ @ L{} {}{} ({})", - indent, entry.line, name, kind_str, location - )); - - // Recurse into children of this entry - for (child_idx, child) in entries.iter().enumerate() { - if child.parent_index == Some(idx) { - format_call(lines, entries, child_idx, depth + 1, &entry.module, &entry.file); - } - } -} diff --git a/src/commands/trace/output_tests.rs b/src/commands/trace/output_tests.rs deleted file mode 100644 index d26d11c..0000000 --- a/src/commands/trace/output_tests.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! Output formatting tests for trace command. - -#[cfg(test)] -mod tests { - use crate::types::{TraceDirection, TraceEntry, TraceResult}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Trace from: MyApp.Controller.index -Max depth: 5 - -No calls found."; - - const SINGLE_TABLE: &str = "\ -Trace from: MyApp.Controller.index -Max depth: 5 - -Found 1 call(s) in chain: - -MyApp.Controller.index/1 [def] (controller.ex:L5:12) - → @ L7 MyApp.Service.fetch/1 [def] (service.ex:L10:20)"; - - const MULTI_DEPTH_TABLE: &str = "\ -Trace from: MyApp.Controller.index -Max depth: 5 - -Found 2 call(s) in chain: - -MyApp.Controller.index/1 [def] (controller.ex:L5:12) - → @ L7 MyApp.Service.fetch/1 [def] (service.ex:L10:20) - → @ L15 MyApp.Repo.get/2 (repo.ex:L30:40)"; - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> TraceResult { - TraceResult { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - max_depth: 5, - direction: TraceDirection::Forward, - total_items: 0, - entries: vec![], - } - } - - #[fixture] - fn single_depth_result() -> TraceResult { - TraceResult { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - max_depth: 5, - direction: TraceDirection::Forward, - total_items: 1, - entries: vec![ - // Root entry: the starting function - TraceEntry { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 5, - end_line: 12, - file: "/path/to/controller.ex".to_string(), - depth: 0, - line: 0, - parent_index: None, - }, - // Callee at depth 1 - TraceEntry { - module: "MyApp.Service".to_string(), - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "/path/to/service.ex".to_string(), - depth: 1, - line: 7, - parent_index: Some(0), - }, - ], - } - } - - #[fixture] - fn multi_depth_result() -> TraceResult { - TraceResult { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - max_depth: 5, - direction: TraceDirection::Forward, - total_items: 2, - entries: vec![ - TraceEntry { - module: "MyApp.Controller".to_string(), - function: "index".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 5, - end_line: 12, - file: "/path/to/controller.ex".to_string(), - depth: 0, - line: 0, - parent_index: None, - }, - TraceEntry { - module: "MyApp.Service".to_string(), - function: "fetch".to_string(), - arity: 1, - kind: "def".to_string(), - start_line: 10, - end_line: 20, - file: "/path/to/service.ex".to_string(), - depth: 1, - line: 7, - parent_index: Some(0), - }, - TraceEntry { - module: "MyApp.Repo".to_string(), - function: "get".to_string(), - arity: 2, - kind: String::new(), - start_line: 30, - end_line: 40, - file: "repo.ex".to_string(), - depth: 2, - line: 15, - parent_index: Some(1), - }, - ], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - #[rstest] - fn test_empty_trace(empty_result: TraceResult) { - use crate::output::Outputable; - let output = empty_result.to_table(); - assert_eq!(output, EMPTY_TABLE); - } - - #[rstest] - fn test_single_depth_trace(single_depth_result: TraceResult) { - use crate::output::Outputable; - let output = single_depth_result.to_table(); - assert_eq!(output, SINGLE_TABLE); - } - - #[rstest] - fn test_multi_depth_trace(multi_depth_result: TraceResult) { - use crate::output::Outputable; - let output = multi_depth_result.to_table(); - assert_eq!(output, MULTI_DEPTH_TABLE); - } -} diff --git a/src/commands/unused/cli_tests.rs b/src/commands/unused/cli_tests.rs deleted file mode 100644 index 26c1ecd..0000000 --- a/src/commands/unused/cli_tests.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! CLI parsing tests for unused command using the test DSL. - -#[cfg(test)] -mod tests { - use crate::cli::Args; - use clap::Parser; - use rstest::rstest; - - // ========================================================================= - // Macro-generated tests (standard patterns) - // ========================================================================= - - // Unused has no required args, so test defaults - crate::cli_defaults_test! { - command: "unused", - variant: Unused, - required_args: [], - defaults: { - common.project: "default", - common.regex: false, - private_only: false, - public_only: false, - exclude_generated: false, - common.limit: 100, - }, - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_module, - args: ["MyApp"], - field: module, - expected: Some("MyApp".to_string()), - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_project, - args: ["--project", "my_app"], - field: common.project, - expected: "my_app", - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_regex, - args: ["MyApp\\..*", "--regex"], - field: common.regex, - expected: true, - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_limit, - args: ["--limit", "50"], - field: common.limit, - expected: 50, - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_private_only, - args: ["--private-only"], - field: private_only, - expected: true, - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_public_only, - args: ["--public-only"], - field: public_only, - expected: true, - } - - crate::cli_option_test! { - command: "unused", - variant: Unused, - test_name: test_with_exclude_generated, - args: ["--exclude-generated"], - field: exclude_generated, - expected: true, - } - - crate::cli_limit_tests! { - command: "unused", - variant: Unused, - required_args: [], - limit: { - field: common.limit, - default: 100, - max: 1000, - }, - } - - // ========================================================================= - // Edge case tests (short flags, conflicts) - // ========================================================================= - - #[rstest] - fn test_with_short_flags() { - let args = Args::try_parse_from(["code_search", "unused", "-p", "-x"]).unwrap(); - match args.command { - crate::commands::Command::Unused(cmd) => { - assert!(cmd.private_only); - assert!(cmd.exclude_generated); - } - _ => panic!("Expected Unused command"), - } - } - - #[rstest] - fn test_public_only_short() { - let args = Args::try_parse_from(["code_search", "unused", "-P"]).unwrap(); - match args.command { - crate::commands::Command::Unused(cmd) => { - assert!(cmd.public_only); - } - _ => panic!("Expected Unused command"), - } - } - - #[rstest] - fn test_private_and_public_conflict() { - let result = - Args::try_parse_from(["code_search", "unused", "--private-only", "--public-only"]); - assert!(result.is_err()); - } -} diff --git a/src/commands/unused/execute.rs b/src/commands/unused/execute.rs deleted file mode 100644 index 77e86b2..0000000 --- a/src/commands/unused/execute.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::error::Error; - -use serde::Serialize; - -use super::UnusedCmd; -use crate::commands::Execute; -use crate::queries::unused::{find_unused_functions, UnusedFunction}; -use crate::types::ModuleCollectionResult; - -/// An unused function within a module -#[derive(Debug, Clone, Serialize)] -pub struct UnusedFunc { - pub name: String, - pub arity: i64, - pub kind: String, - pub line: i64, -} - -impl ModuleCollectionResult { - /// Build grouped result from flat UnusedFunction list - fn from_functions( - module_pattern: String, - functions: Vec, - ) -> Self { - let total_items = functions.len(); - - // Use helper to group by module, tracking file for each module - let items = crate::utils::group_by_module_with_file(functions, |func| { - let unused_func = UnusedFunc { - name: func.name, - arity: func.arity, - kind: func.kind, - line: func.line, - }; - (func.module, unused_func, func.file) - }); - - ModuleCollectionResult { - module_pattern, - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items, - items, - } - } -} - -impl Execute for UnusedCmd { - type Output = ModuleCollectionResult; - - fn execute(self, db: &cozo::DbInstance) -> Result> { - let functions = find_unused_functions( - db, - self.module.as_deref(), - &self.common.project, - self.common.regex, - self.private_only, - self.public_only, - self.exclude_generated, - self.common.limit, - )?; - - Ok(>::from_functions( - self.module.unwrap_or_else(|| "*".to_string()), - functions, - )) - } -} - diff --git a/src/commands/unused/execute_tests.rs b/src/commands/unused/execute_tests.rs deleted file mode 100644 index 6a04534..0000000 --- a/src/commands/unused/execute_tests.rs +++ /dev/null @@ -1,195 +0,0 @@ -//! Execute tests for unused command. - -#[cfg(test)] -mod tests { - use super::super::UnusedCmd; - use crate::commands::CommonArgs; - use rstest::{fixture, rstest}; - - crate::shared_fixture! { - fixture_name: populated_db, - fixture_type: call_graph, - project: "test_project", - } - - // ========================================================================= - // Core functionality tests - // ========================================================================= - - // Uncalled functions: index, show, create (Controller), get_user/2 + validate_email (Accounts), insert (Repo) = 6 - // Note: get_user/1 is called but get_user/2 is not (Controller.show calls arity 1 only) - crate::execute_test! { - test_name: test_unused_finds_uncalled_functions, - fixture: populated_db, - cmd: UnusedCmd { - module: None, - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 6); - let all_funcs: Vec<&str> = result.items.iter() - .flat_map(|m| m.entries.iter().map(|f| f.name.as_str())) - .collect(); - assert!(all_funcs.contains(&"validate_email")); - assert!(all_funcs.contains(&"insert")); - }, - } - - // In Accounts: validate_email (defp) and get_user/2 (def, not called) = 2 - crate::execute_test! { - test_name: test_unused_with_module_filter, - fixture: populated_db, - cmd: UnusedCmd { - module: Some("Accounts".to_string()), - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 2); - }, - } - - // Controller has 3 uncalled functions - crate::execute_test! { - test_name: test_unused_with_regex_filter, - fixture: populated_db, - cmd: UnusedCmd { - module: Some("^MyApp\\.Controller$".to_string()), - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: true, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 3); - }, - } - - // ========================================================================= - // No match / empty result tests - // ========================================================================= - - crate::execute_no_match_test! { - test_name: test_unused_no_match, - fixture: populated_db, - cmd: UnusedCmd { - module: Some("NonExistent".to_string()), - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - empty_field: items, - } - - // ========================================================================= - // Filter tests - // ========================================================================= - - crate::execute_test! { - test_name: test_unused_with_limit, - fixture: populated_db, - cmd: UnusedCmd { - module: None, - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 1, - }, - }, - assertions: |result| { - // Limit applies to raw results before grouping - assert_eq!(result.total_items, 1); - }, - } - - // validate_email is the only private (defp) uncalled function - crate::execute_test! { - test_name: test_unused_private_only, - fixture: populated_db, - cmd: UnusedCmd { - module: None, - private_only: true, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 1); - assert_eq!(result.items[0].entries[0].name, "validate_email"); - assert_eq!(result.items[0].entries[0].kind, "defp"); - }, - } - - // 5 public uncalled: index, show, create (Controller), get_user/2 (Accounts), insert (Repo) - crate::execute_test! { - test_name: test_unused_public_only, - fixture: populated_db, - cmd: UnusedCmd { - module: None, - private_only: false, - public_only: true, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - assertions: |result| { - assert_eq!(result.total_items, 5); - for module in &result.items { - for func in &module.entries { - assert_eq!(func.kind, "def"); - } - } - }, - } - - // ========================================================================= - // Error handling tests - // ========================================================================= - - crate::execute_empty_db_test! { - cmd_type: UnusedCmd, - cmd: UnusedCmd { - module: None, - private_only: false, - public_only: false, - exclude_generated: false, - common: CommonArgs { - project: "test_project".to_string(), - regex: false, - limit: 100, - }, - }, - } -} diff --git a/src/commands/unused/mod.rs b/src/commands/unused/mod.rs deleted file mode 100644 index 2304e99..0000000 --- a/src/commands/unused/mod.rs +++ /dev/null @@ -1,50 +0,0 @@ -mod cli_tests; -mod execute; -mod execute_tests; -mod output; -mod output_tests; - -use std::error::Error; - -use clap::Args; -use cozo::DbInstance; - -use crate::commands::{CommandRunner, CommonArgs, Execute}; -use crate::output::{OutputFormat, Outputable}; - -/// Find functions that are never called -#[derive(Args, Debug)] -#[command(after_help = "\ -Examples: - code_search unused # Find all unused functions - code_search unused MyApp.Accounts # Filter to specific module - code_search unused -P # Unused public functions (entry points) - code_search unused -p # Unused private functions (dead code) - code_search unused -Px # Public only, exclude generated - code_search unused 'Accounts.*' -r # Match module with regex")] -pub struct UnusedCmd { - /// Module pattern to filter results (substring match by default, regex with -r) - pub module: Option, - - /// Only show private functions (defp, defmacrop) - likely dead code - #[arg(short, long, default_value_t = false, conflicts_with = "public_only")] - pub private_only: bool, - - /// Only show public functions (def, defmacro) - potential entry points - #[arg(short = 'P', long, default_value_t = false, conflicts_with = "private_only")] - pub public_only: bool, - - /// Exclude compiler-generated functions (__struct__, __info__, etc.) - #[arg(short = 'x', long, default_value_t = false)] - pub exclude_generated: bool, - - #[command(flatten)] - pub common: CommonArgs, -} - -impl CommandRunner for UnusedCmd { - fn run(self, db: &DbInstance, format: OutputFormat) -> Result> { - let result = self.execute(db)?; - Ok(result.format(format)) - } -} diff --git a/src/commands/unused/output.rs b/src/commands/unused/output.rs deleted file mode 100644 index 2ca5e6b..0000000 --- a/src/commands/unused/output.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Output formatting for unused command results. - -use crate::output::Outputable; -use crate::types::ModuleCollectionResult; -use super::execute::UnusedFunc; - -impl Outputable for ModuleCollectionResult { - fn to_table(&self) -> String { - let mut lines = Vec::new(); - - let filter_info = if self.module_pattern != "*" { - format!(" (module: {})", self.module_pattern) - } else { - String::new() - }; - - lines.push(format!("Unused functions{}", filter_info)); - lines.push(String::new()); - - if !self.items.is_empty() { - lines.push(format!( - "Found {} unused function(s) in {} module(s):", - self.total_items, - self.items.len() - )); - lines.push(String::new()); - - for module in &self.items { - lines.push(format!("{} ({}):", module.name, module.file)); - for func in &module.entries { - lines.push(format!( - " {}/{} [{}] L{}", - func.name, func.arity, func.kind, func.line - )); - } - } - } else { - lines.push("No unused functions found.".to_string()); - } - - lines.join("\n") - } -} diff --git a/src/commands/unused/output_tests.rs b/src/commands/unused/output_tests.rs deleted file mode 100644 index 096bb96..0000000 --- a/src/commands/unused/output_tests.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! Output formatting tests for unused command. - -#[cfg(test)] -mod tests { - use super::super::execute::UnusedFunc; - use crate::types::{ModuleCollectionResult, ModuleGroup}; - use rstest::{fixture, rstest}; - - // ========================================================================= - // Expected outputs - // ========================================================================= - - const EMPTY_TABLE: &str = "\ -Unused functions - -No unused functions found."; - - const SINGLE_TABLE: &str = "\ -Unused functions - -Found 1 unused function(s) in 1 module(s): - -MyApp.Accounts (lib/accounts.ex): - unused_helper/0 [defp] L35"; - - const FILTERED_TABLE: &str = "\ -Unused functions (module: Accounts) - -Found 1 unused function(s) in 1 module(s): - -MyApp.Accounts (lib/accounts.ex): - unused_helper/0 [defp] L35"; - - - // ========================================================================= - // Fixtures - // ========================================================================= - - #[fixture] - fn empty_result() -> ModuleCollectionResult { - ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 0, - items: vec![], - } - } - - #[fixture] - fn single_result() -> ModuleCollectionResult { - ModuleCollectionResult { - module_pattern: "*".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - entries: vec![UnusedFunc { - name: "unused_helper".to_string(), - arity: 0, - kind: "defp".to_string(), - line: 35, - }], - function_count: None, - }], - } - } - - #[fixture] - fn filtered_result() -> ModuleCollectionResult { - ModuleCollectionResult { - module_pattern: "Accounts".to_string(), - function_pattern: None, - kind_filter: None, - name_filter: None, - total_items: 1, - items: vec![ModuleGroup { - name: "MyApp.Accounts".to_string(), - file: "lib/accounts.ex".to_string(), - entries: vec![UnusedFunc { - name: "unused_helper".to_string(), - arity: 0, - kind: "defp".to_string(), - line: 35, - }], - function_count: None, - }], - } - } - - // ========================================================================= - // Tests - // ========================================================================= - - crate::output_table_test! { - test_name: test_to_table_empty, - fixture: empty_result, - fixture_type: ModuleCollectionResult, - expected: EMPTY_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_single, - fixture: single_result, - fixture_type: ModuleCollectionResult, - expected: SINGLE_TABLE, - } - - crate::output_table_test! { - test_name: test_to_table_filtered, - fixture: filtered_result, - fixture_type: ModuleCollectionResult, - expected: FILTERED_TABLE, - } - - crate::output_table_test! { - test_name: test_format_json, - fixture: single_result, - fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "single.json"), - format: Json, - } - - crate::output_table_test! { - test_name: test_format_toon, - fixture: single_result, - fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "single.toon"), - format: Toon, - } - - crate::output_table_test! { - test_name: test_format_toon_empty, - fixture: empty_result, - fixture_type: ModuleCollectionResult, - expected: crate::test_utils::load_output_fixture("unused", "empty.toon"), - format: Toon, - } -} diff --git a/src/db.rs b/src/db.rs deleted file mode 100644 index e74370d..0000000 --- a/src/db.rs +++ /dev/null @@ -1,504 +0,0 @@ -//! Database connection and query utilities for CozoDB. -//! -//! This module provides the database abstraction layer for the CLI tool: -//! - Connection management (SQLite-backed or in-memory for tests) -//! - Query execution with parameter binding -//! - Result row extraction with type-safe helpers -//! -//! # Architecture -//! -//! CozoDB is a Datalog database that stores call graph data in relations. -//! Queries are written in CozoScript (a Datalog variant) and return `NamedRows` -//! containing `DataValue` cells that must be extracted into Rust types. -//! -//! # Type Decisions -//! -//! **Why `i64` for arity/line numbers instead of `u32`?** -//! CozoDB returns all integers as `Num::Int(i64)`. Using `i64` throughout avoids -//! lossy conversions and potential panics. The semantic constraint (arity >= 0) -//! is enforced by the data source (Elixir AST), not runtime checks. -//! -//! **Why `CallRowLayout` with indices instead of serde deserialization?** -//! CozoDB returns rows as `Vec`, not JSON objects. The `CallRowLayout` -//! struct documents column positions for each query type, centralizing the -//! mapping in two factory methods rather than scattering magic numbers. -//! -//! **Why bare `String` for module/function names instead of newtypes?** -//! For a CLI tool, the complexity of newtype wrappers (`.0` access, `Into` impls, -//! derive macro limitations) outweighs the type safety benefit. Field names -//! (`module`, `name`) are sufficiently clear. - -use std::collections::{BTreeMap, HashMap}; -use std::error::Error; -use std::path::Path; -use std::rc::Rc; - -use cozo::{DataValue, DbInstance, NamedRows, ScriptMutability}; -use thiserror::Error; - -use crate::types::{Call, FunctionRef}; - -#[derive(Error, Debug)] -pub enum DbError { - #[error("Failed to open database '{path}': {message}")] - OpenFailed { path: String, message: String }, - - #[error("Query failed: {message}")] - QueryFailed { message: String }, - - #[error("Missing column '{name}' in query result")] - MissingColumn { name: String }, -} - -pub type Params = BTreeMap; - -pub fn open_db(path: &Path) -> Result> { - DbInstance::new("sqlite", path, "").map_err(|e| { - Box::new(DbError::OpenFailed { - path: path.display().to_string(), - message: format!("{:?}", e), - }) as Box - }) -} - -/// Create an in-memory database instance. -/// -/// Used for tests to avoid disk I/O and temp file management. -#[cfg(test)] -pub fn open_mem_db() -> DbInstance { - DbInstance::new("mem", "", "").expect("Failed to create in-memory DB") -} - -/// Run a mutable query (insert, delete, create, etc.) -pub fn run_query( - db: &DbInstance, - script: &str, - params: Params, -) -> Result> { - db.run_script(script, params, ScriptMutability::Mutable) - .map_err(|e| { - Box::new(DbError::QueryFailed { - message: format!("{:?}", e), - }) as Box - }) -} - -/// Run a mutable query with no parameters -pub fn run_query_no_params(db: &DbInstance, script: &str) -> Result> { - run_query(db, script, Params::new()) -} - -/// Escape a string for use in CozoDB string literals. -/// -/// # Arguments -/// * `s` - The string to escape -/// * `quote_char` - The quote character to escape ('"' for double-quoted, '\'' for single-quoted) -pub fn escape_string_for_quote(s: &str, quote_char: char) -> String { - let mut result = String::with_capacity(s.len() * 2); - for c in s.chars() { - match c { - '\\' => result.push_str("\\\\"), - c if c == quote_char => { - result.push('\\'); - result.push(c); - } - '\n' => result.push_str("\\n"), - '\r' => result.push_str("\\r"), - '\t' => result.push_str("\\t"), - c if c.is_control() || c == '\0' => { - // Escape control characters as \uXXXX (JSON format) - result.push_str(&format!("\\u{:04x}", c as u32)); - } - c => result.push(c), - } - } - result -} - -/// Escape a string for use in CozoDB double-quoted string literals (JSON-compatible) -#[inline] -pub fn escape_string(s: &str) -> String { - escape_string_for_quote(s, '"') -} - -/// Escape a string for use in CozoDB single-quoted string literals. -/// Use this for strings that may contain double quotes or complex content. -#[inline] -pub fn escape_string_single(s: &str) -> String { - escape_string_for_quote(s, '\'') -} - -/// Try to create a relation, returning Ok(true) if created, Ok(false) if already exists -pub fn try_create_relation(db: &DbInstance, script: &str) -> Result> { - match run_query_no_params(db, script) { - Ok(_) => Ok(true), - Err(e) => { - let err_str = e.to_string(); - if err_str.contains("AlreadyExists") || err_str.contains("stored_relation_conflict") { - Ok(false) - } else { - Err(e) - } - } - } -} - -// DataValue extraction helpers - -use cozo::Num; - -/// Extract a String from a DataValue, returning None if not a string -pub fn extract_string(value: &DataValue) -> Option { - match value { - DataValue::Str(s) => Some(s.to_string()), - _ => None, - } -} - -/// Extract an i64 from a DataValue, returning the default if not a number -pub fn extract_i64(value: &DataValue, default: i64) -> i64 { - match value { - DataValue::Num(Num::Int(i)) => *i, - DataValue::Num(Num::Float(f)) => *f as i64, - _ => default, - } -} - -/// Extract a String from a DataValue, returning the default if not a string -pub fn extract_string_or(value: &DataValue, default: &str) -> String { - match value { - DataValue::Str(s) => s.to_string(), - _ => default.to_string(), - } -} - -/// Extract a bool from a DataValue, returning the default if not a bool -pub fn extract_bool(value: &DataValue, default: bool) -> bool { - match value { - DataValue::Bool(b) => *b, - _ => default, - } -} - -/// Extract an f64 from a DataValue, returning the default if not a number -pub fn extract_f64(value: &DataValue, default: f64) -> f64 { - match value { - DataValue::Num(Num::Int(i)) => *i as f64, - DataValue::Num(Num::Float(f)) => *f, - _ => default, - } -} - -/// Layout descriptor for extracting call data from query result rows -#[derive(Debug)] -pub struct CallRowLayout { - pub caller_module_idx: usize, - pub caller_name_idx: usize, - pub caller_arity_idx: usize, - pub caller_kind_idx: usize, - pub caller_start_line_idx: usize, - pub caller_end_line_idx: usize, - pub callee_module_idx: usize, - pub callee_name_idx: usize, - pub callee_arity_idx: usize, - pub file_idx: usize, - pub line_idx: usize, - pub call_type_idx: Option, -} - -impl CallRowLayout { - /// Build layout dynamically from query result headers. - /// - /// This looks up column positions by name, making queries resilient to - /// column reordering. Returns error if any required column is missing. - /// - /// Expected column names (from CozoScript queries): - /// - caller_module, caller_name, caller_arity, caller_kind - /// - caller_start_line, caller_end_line - /// - callee_module, callee_function, callee_arity - /// - file, call_line - /// - call_type (optional) - pub fn from_headers(headers: &[String]) -> Result { - // Build lookup map once: O(m) where m = number of headers - let header_map: HashMap<&str, usize> = headers - .iter() - .enumerate() - .map(|(i, h)| (h.as_str(), i)) - .collect(); - - // Helper for required columns: O(1) each - let find = |name: &str| -> Result { - header_map - .get(name) - .copied() - .ok_or_else(|| DbError::MissingColumn { - name: name.to_string(), - }) - }; - - Ok(Self { - caller_module_idx: find("caller_module")?, - caller_name_idx: find("caller_name")?, - caller_arity_idx: find("caller_arity")?, - caller_kind_idx: find("caller_kind")?, - caller_start_line_idx: find("caller_start_line")?, - caller_end_line_idx: find("caller_end_line")?, - callee_module_idx: find("callee_module")?, - callee_name_idx: find("callee_function")?, - callee_arity_idx: find("callee_arity")?, - file_idx: find("file")?, - line_idx: find("call_line")?, - call_type_idx: header_map.get("call_type").copied(), - }) - } -} - -/// Extract call data from a query result row -/// -/// Returns Option if all required fields are present. Uses early return -/// (None) if any required string field cannot be extracted. -pub fn extract_call_from_row(row: &[DataValue], layout: &CallRowLayout) -> Option { - // Extract caller information - let Some(caller_module) = extract_string(&row[layout.caller_module_idx]) else { return None }; - let Some(caller_name) = extract_string(&row[layout.caller_name_idx]) else { return None }; - let caller_arity = extract_i64(&row[layout.caller_arity_idx], 0); - let caller_kind = extract_string_or(&row[layout.caller_kind_idx], ""); - let caller_start_line = extract_i64(&row[layout.caller_start_line_idx], 0); - let caller_end_line = extract_i64(&row[layout.caller_end_line_idx], 0); - - // Extract callee information - let Some(callee_module) = extract_string(&row[layout.callee_module_idx]) else { return None }; - let Some(callee_name) = extract_string(&row[layout.callee_name_idx]) else { return None }; - let callee_arity = extract_i64(&row[layout.callee_arity_idx], 0); - - // Extract file and line - let Some(file) = extract_string(&row[layout.file_idx]) else { return None }; - let line = extract_i64(&row[layout.line_idx], 0); - - // Extract optional call_type - let call_type = layout.call_type_idx.and_then(|idx| { - if idx < row.len() { - Some(extract_string_or(&row[idx], "remote")) - } else { - None - } - }); - - // Create FunctionRef objects with Rc to reduce memory allocations - let caller = FunctionRef::with_definition( - Rc::from(caller_module.into_boxed_str()), - Rc::from(caller_name.into_boxed_str()), - caller_arity, - Rc::from(caller_kind.into_boxed_str()), - Rc::from(file.into_boxed_str()), - caller_start_line, - caller_end_line, - ); - - let callee = FunctionRef::new( - Rc::from(callee_module.into_boxed_str()), - Rc::from(callee_name.into_boxed_str()), - callee_arity, - ); - - // Return Call - Some(Call { - caller, - callee, - line, - call_type, - depth: None, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use cozo::Num; - use rstest::rstest; - - #[rstest] - fn test_extract_string_from_str() { - let value = DataValue::Str("hello".into()); - assert_eq!(extract_string(&value), Some("hello".to_string())); - } - - #[rstest] - fn test_extract_string_from_non_str() { - let value = DataValue::Num(Num::Int(42)); - assert_eq!(extract_string(&value), None); - } - - #[rstest] - fn test_extract_i64_from_int() { - let value = DataValue::Num(Num::Int(42)); - assert_eq!(extract_i64(&value, 0), 42); - } - - #[rstest] - fn test_extract_i64_from_float() { - let value = DataValue::Num(Num::Float(42.7)); - assert_eq!(extract_i64(&value, 0), 42); - } - - #[rstest] - fn test_extract_i64_from_non_num() { - let value = DataValue::Str("not a number".into()); - assert_eq!(extract_i64(&value, -1), -1); - } - - #[rstest] - fn test_extract_string_or_from_str() { - let value = DataValue::Str("hello".into()); - assert_eq!(extract_string_or(&value, "default"), "hello"); - } - - #[rstest] - fn test_extract_string_or_from_non_str() { - let value = DataValue::Num(Num::Int(42)); - assert_eq!(extract_string_or(&value, "default"), "default"); - } - - #[rstest] - fn test_escape_string_basic() { - assert_eq!(escape_string("hello"), "hello"); - } - - #[rstest] - fn test_escape_string_with_quotes() { - assert_eq!(escape_string(r#"say "hello""#), r#"say \"hello\""#); - } - - #[rstest] - fn test_escape_string_with_backslash() { - assert_eq!(escape_string(r"path\to\file"), r"path\\to\\file"); - } - - #[rstest] - fn test_extract_bool_from_bool() { - let value = DataValue::Bool(true); - assert_eq!(extract_bool(&value, false), true); - } - - #[rstest] - fn test_extract_bool_from_non_bool() { - let value = DataValue::Str("true".into()); - assert_eq!(extract_bool(&value, false), false); - } - - // CallRowLayout::from_headers tests - - fn standard_headers() -> Vec { - vec![ - "caller_module", - "caller_name", - "caller_arity", - "caller_kind", - "caller_start_line", - "caller_end_line", - "callee_module", - "callee_function", - "callee_arity", - "file", - "call_line", - ] - .into_iter() - .map(String::from) - .collect() - } - - #[rstest] - fn test_from_headers_all_required_columns() { - let headers = standard_headers(); - let layout = CallRowLayout::from_headers(&headers).unwrap(); - - assert_eq!(layout.caller_module_idx, 0); - assert_eq!(layout.caller_name_idx, 1); - assert_eq!(layout.caller_arity_idx, 2); - assert_eq!(layout.caller_kind_idx, 3); - assert_eq!(layout.caller_start_line_idx, 4); - assert_eq!(layout.caller_end_line_idx, 5); - assert_eq!(layout.callee_module_idx, 6); - assert_eq!(layout.callee_name_idx, 7); - assert_eq!(layout.callee_arity_idx, 8); - assert_eq!(layout.file_idx, 9); - assert_eq!(layout.line_idx, 10); - assert_eq!(layout.call_type_idx, None); - } - - #[rstest] - fn test_from_headers_with_optional_call_type() { - let mut headers = standard_headers(); - headers.push("call_type".to_string()); - - let layout = CallRowLayout::from_headers(&headers).unwrap(); - assert_eq!(layout.call_type_idx, Some(11)); - } - - #[rstest] - fn test_from_headers_different_column_order() { - // Columns in different order - the key benefit of dynamic lookup - let headers: Vec = vec![ - "file", - "callee_module", - "caller_module", - "call_line", - "caller_name", - "callee_function", - "caller_arity", - "callee_arity", - "caller_kind", - "caller_start_line", - "caller_end_line", - "call_type", - ] - .into_iter() - .map(String::from) - .collect(); - - let layout = CallRowLayout::from_headers(&headers).unwrap(); - - assert_eq!(layout.file_idx, 0); - assert_eq!(layout.callee_module_idx, 1); - assert_eq!(layout.caller_module_idx, 2); - assert_eq!(layout.line_idx, 3); - assert_eq!(layout.caller_name_idx, 4); - assert_eq!(layout.callee_name_idx, 5); - assert_eq!(layout.caller_arity_idx, 6); - assert_eq!(layout.callee_arity_idx, 7); - assert_eq!(layout.caller_kind_idx, 8); - assert_eq!(layout.caller_start_line_idx, 9); - assert_eq!(layout.caller_end_line_idx, 10); - assert_eq!(layout.call_type_idx, Some(11)); - } - - #[rstest] - fn test_from_headers_missing_required_column() { - let headers: Vec = vec![ - "caller_module", - "caller_name", - // missing caller_arity - "caller_kind", - ] - .into_iter() - .map(String::from) - .collect(); - - let result = CallRowLayout::from_headers(&headers); - assert!(result.is_err()); - - let err = result.unwrap_err(); - assert!(matches!(err, DbError::MissingColumn { name } if name == "caller_arity")); - } - - #[rstest] - fn test_from_headers_error_message() { - let headers: Vec = vec!["caller_module".to_string()]; - - let err = CallRowLayout::from_headers(&headers).unwrap_err(); - assert_eq!( - err.to_string(), - "Missing column 'caller_name' in query result" - ); - } -} diff --git a/src/dedup.rs b/src/dedup.rs deleted file mode 100644 index 6fd3e55..0000000 --- a/src/dedup.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Deduplication utilities for reducing code duplication across commands. -//! -//! This module provides reusable patterns for deduplicating collections using different strategies: -//! - Strategy A: HashSet retain pattern (deduplicate_retain) - for in-place deduplication after sorting -//! - Strategy B: HashSet prevention pattern (DeduplicationFilter) - for preventing duplicates during collection - -use std::collections::HashSet; -use std::hash::Hash; - -/// Strategy A: HashSet retain pattern - deduplicate in-place -/// -/// Use this when you have a collection that's already been sorted, and you want to remove -/// duplicate entries while preserving the sort order. -/// -/// # Arguments -/// * `items` - Mutable vector of items to deduplicate -/// * `key_fn` - Function that extracts the deduplication key from each item -/// -/// # Example -/// ```ignore -/// let mut calls = vec![...]; -/// calls.sort_by_key(|c| c.line); -/// deduplicate_retain(&mut calls, |c| { -/// (c.callee.module.clone(), c.callee.name.clone(), c.callee.arity) -/// }); -/// ``` -pub fn deduplicate_retain(items: &mut Vec, key_fn: F) -where - F: Fn(&T) -> K, - K: Eq + Hash, -{ - let mut seen: HashSet = HashSet::new(); - items.retain(|item| seen.insert(key_fn(item))); -} - -/// Combined sort and deduplicate operation. -/// -/// Sorts a collection using a comparator, then deduplicates using a different key. -/// Preserves the first occurrence of each duplicate. -/// -/// Use this when you need to: -/// 1. Sort items by one criteria (e.g., line number) -/// 2. Remove duplicates based on different criteria (e.g., callee name) -/// -/// # Arguments -/// * `items` - Mutable vector of items to sort and deduplicate -/// * `sort_cmp` - Comparator function that returns the ordering between two items -/// * `dedup_key_fn` - Function that extracts the deduplication key -/// -/// # Example -/// ```ignore -/// let mut calls = vec![...]; -/// sort_and_deduplicate( -/// &mut calls, -/// |a, b| a.line.cmp(&b.line), // Sort by line number - no allocation -/// |c| (c.callee.module.clone(), c.callee.name.clone(), c.callee.arity) // Dedup by callee -/// ); -/// ``` -pub fn sort_and_deduplicate( - items: &mut Vec, - sort_cmp: SC, - dedup_key: DK, -) -where - SC: FnMut(&T, &T) -> std::cmp::Ordering, - DK: Fn(&T) -> D, - D: Eq + Hash, -{ - items.sort_by(sort_cmp); - deduplicate_retain(items, dedup_key); -} - -/// Strategy B: HashSet prevention pattern - check before adding -/// -/// Use this when collecting items and you want to prevent duplicates from being added -/// in the first place, without needing to sort or post-process. -/// -/// # Example -/// ```ignore -/// let mut filter = DeduplicationFilter::new(); -/// for entry in entries { -/// if filter.should_process(entry_key) { -/// // Add entry to result -/// } -/// } -/// ``` -#[derive(Debug)] -pub struct DeduplicationFilter { - processed: HashSet, -} - -impl DeduplicationFilter { - /// Create a new empty deduplication filter - pub fn new() -> Self { - Self { - processed: HashSet::new(), - } - } - - /// Check if a key should be processed (inserted into the set) - /// - /// Returns true if the key is new and was successfully inserted, false if it was already present. - pub fn should_process(&mut self, key: K) -> bool { - self.processed.insert(key) - } -} - -impl Default for DeduplicationFilter { - fn default() -> Self { - Self::new() - } -} diff --git a/src/fixtures/call_graph.json b/src/fixtures/call_graph.json deleted file mode 100644 index 981814f..0000000 --- a/src/fixtures/call_graph.json +++ /dev/null @@ -1,468 +0,0 @@ -{ - "structs": {}, - "function_locations": { - "MyApp.Controller": { - "index/2:5": { - "file": "lib/my_app/controller.ex", - "column": 3, - "kind": "def", - "line": 5, - "start_line": 5, - "end_line": 10, - "pattern": "conn, params", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "index", - "arity": 2 - }, - "show/2:12": { - "file": "lib/my_app/controller.ex", - "column": 3, - "kind": "def", - "line": 12, - "start_line": 12, - "end_line": 18, - "pattern": "conn, params", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "show", - "arity": 2 - }, - "create/2:20": { - "file": "lib/my_app/controller.ex", - "column": 3, - "kind": "def", - "line": 20, - "start_line": 20, - "end_line": 30, - "pattern": "conn, params", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "create", - "arity": 2 - } - }, - "MyApp.Accounts": { - "get_user/1:10": { - "file": "lib/my_app/accounts.ex", - "column": 3, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15, - "pattern": "id", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "get_user", - "arity": 1 - }, - "get_user/2:17": { - "file": "lib/my_app/accounts.ex", - "column": 3, - "kind": "def", - "line": 17, - "start_line": 17, - "end_line": 22, - "pattern": "id, opts", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "get_user", - "arity": 2 - }, - "list_users/0:24": { - "file": "lib/my_app/accounts.ex", - "column": 3, - "kind": "def", - "line": 24, - "start_line": 24, - "end_line": 28, - "pattern": "", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "list_users", - "arity": 0 - }, - "validate_email/1:30": { - "file": "lib/my_app/accounts.ex", - "column": 3, - "kind": "defp", - "line": 30, - "start_line": 30, - "end_line": 35, - "pattern": "email", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "validate_email", - "arity": 1 - } - }, - "MyApp.Service": { - "process/1:5": { - "file": "lib/my_app/service.ex", - "column": 3, - "kind": "def", - "line": 5, - "start_line": 5, - "end_line": 15, - "pattern": "data", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "process", - "arity": 1 - }, - "fetch/1:17": { - "file": "lib/my_app/service.ex", - "column": 3, - "kind": "def", - "line": 17, - "start_line": 17, - "end_line": 25, - "pattern": "id", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "fetch", - "arity": 1 - }, - "do_fetch/2:27": { - "file": "lib/my_app/service.ex", - "column": 3, - "kind": "defp", - "line": 27, - "start_line": 27, - "end_line": 35, - "pattern": "id, opts", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "do_fetch", - "arity": 2 - } - }, - "MyApp.Repo": { - "get/2:10": { - "file": "lib/my_app/repo.ex", - "column": 3, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15, - "pattern": "schema, id", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "get", - "arity": 2 - }, - "all/1:17": { - "file": "lib/my_app/repo.ex", - "column": 3, - "kind": "def", - "line": 17, - "start_line": 17, - "end_line": 22, - "pattern": "query", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "all", - "arity": 1 - }, - "insert/2:24": { - "file": "lib/my_app/repo.ex", - "column": 3, - "kind": "def", - "line": 24, - "start_line": 24, - "end_line": 30, - "pattern": "struct, opts", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "insert", - "arity": 2 - } - }, - "MyApp.Notifier": { - "notify/1:5": { - "file": "lib/my_app/notifier.ex", - "column": 3, - "kind": "def", - "line": 5, - "start_line": 5, - "end_line": 12, - "pattern": "user", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "notify", - "arity": 1 - }, - "send_email/2:14": { - "file": "lib/my_app/notifier.ex", - "column": 3, - "kind": "defp", - "line": 14, - "start_line": 14, - "end_line": 20, - "pattern": "to, body", - "guard": null, - "source_sha": "", - "ast_sha": "", - "name": "send_email", - "arity": 2 - } - } - }, - "calls": [ - { - "caller": { - "module": "MyApp.Controller", - "function": "index", - "file": "lib/my_app/controller.ex", - "line": 7, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 0, - "function": "list_users", - "module": "MyApp.Accounts" - } - }, - { - "caller": { - "module": "MyApp.Controller", - "function": "show", - "file": "lib/my_app/controller.ex", - "line": 14, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 1, - "function": "get_user", - "module": "MyApp.Accounts" - } - }, - { - "caller": { - "module": "MyApp.Controller", - "function": "create", - "file": "lib/my_app/controller.ex", - "line": 22, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 1, - "function": "process", - "module": "MyApp.Service" - } - }, - { - "caller": { - "module": "MyApp.Accounts", - "function": "get_user", - "file": "lib/my_app/accounts.ex", - "line": 12, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 2, - "function": "get", - "module": "MyApp.Repo" - } - }, - { - "caller": { - "module": "MyApp.Accounts", - "function": "get_user", - "file": "lib/my_app/accounts.ex", - "line": 19, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 2, - "function": "get", - "module": "MyApp.Repo" - } - }, - { - "caller": { - "module": "MyApp.Accounts", - "function": "list_users", - "file": "lib/my_app/accounts.ex", - "line": 26, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 1, - "function": "all", - "module": "MyApp.Repo" - } - }, - { - "caller": { - "module": "MyApp.Service", - "function": "process", - "file": "lib/my_app/service.ex", - "line": 8, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 1, - "function": "fetch", - "module": "MyApp.Service" - } - }, - { - "caller": { - "module": "MyApp.Service", - "function": "fetch", - "file": "lib/my_app/service.ex", - "line": 20, - "column": 5 - }, - "type": "local", - "callee": { - "arity": 2, - "function": "do_fetch", - "module": "MyApp.Service" - } - }, - { - "caller": { - "module": "MyApp.Service", - "function": "do_fetch", - "file": "lib/my_app/service.ex", - "line": 30, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 2, - "function": "get", - "module": "MyApp.Repo" - } - }, - { - "caller": { - "module": "MyApp.Service", - "function": "process", - "file": "lib/my_app/service.ex", - "line": 12, - "column": 5 - }, - "type": "remote", - "callee": { - "arity": 1, - "function": "notify", - "module": "MyApp.Notifier" - } - }, - { - "caller": { - "module": "MyApp.Notifier", - "function": "notify", - "file": "lib/my_app/notifier.ex", - "line": 8, - "column": 5 - }, - "type": "local", - "callee": { - "arity": 2, - "function": "send_email", - "module": "MyApp.Notifier" - } - } - ], - "specs": { - "MyApp.Accounts": [ - { - "name": "get_user", - "arity": 1, - "kind": "spec", - "line": 8, - "clauses": [ - { - "full": "@spec get_user(integer()) :: {:ok, User.t()} | {:error, :not_found}", - "input_strings": [ - "integer()" - ], - "return_strings": [ - "{:ok, User.t()}", - "{:error, :not_found}" - ] - } - ] - }, - { - "name": "list_users", - "arity": 0, - "kind": "spec", - "line": 22, - "clauses": [ - { - "full": "@spec list_users() :: [User.t()]", - "input_strings": [], - "return_strings": [ - "[User.t()]" - ] - } - ] - } - ], - "MyApp.Repo": [ - { - "name": "get", - "arity": 2, - "kind": "callback", - "line": 8, - "clauses": [ - { - "full": "@callback get(module(), term()) :: Ecto.Schema.t() | nil", - "input_strings": [ - "module()", - "term()" - ], - "return_strings": [ - "Ecto.Schema.t()", - "nil" - ] - } - ] - } - ] - }, - "types": { - "MyApp.Accounts": [ - { - "name": "user", - "kind": "type", - "line": 5, - "params": [], - "definition": "@type user() :: %{id: integer(), name: String.t()}" - }, - { - "name": "user_id", - "kind": "opaque", - "line": 3, - "params": [], - "definition": "@opaque user_id() :: integer()" - } - ] - } -} diff --git a/src/fixtures/extracted_trace.json b/src/fixtures/extracted_trace.json deleted file mode 100644 index 472515d..0000000 --- a/src/fixtures/extracted_trace.json +++ /dev/null @@ -1,53152 +0,0 @@ -{ - "specs": { - "Phoenix.Logger": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Notifier": [ - { - "arity": 1, - "line": 140, - "name": "raise_with_help", - "clauses": [ - { - "full": "@spec raise_with_help(String.t()) :: no_return()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 181, - "name": "maybe_print_mailer_installation_instructions", - "clauses": [ - { - "full": "@spec maybe_print_mailer_installation_instructions(%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}) :: %{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}", - "input_strings": [ - "%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}" - ], - "return_strings": [ - "%{__struct__: Mix.Phoenix.Context, alias: term(), base_module: term(), basename: term(), context_app: term(), dir: term(), file: term(), generate?: term(), module: term(), name: term(), opts: term(), schema: term(), scope: term(), test_file: term(), test_fixtures_file: term(), web_module: term()}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Channel": [ - { - "arity": 2, - "line": 436, - "name": "terminate", - "clauses": [ - { - "full": "@callback terminate(:normal | :shutdown | {:shutdown, :left | :closed | term()}, Phoenix.Socket.t()) :: term()", - "input_strings": [ - ":normal | :shutdown | {:shutdown, :left | :closed | term()}", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 364, - "name": "join", - "clauses": [ - { - "full": "@callback join(binary(), payload(), Phoenix.Socket.t()) :: {:ok, Phoenix.Socket.t()} | {:ok, payload(), Phoenix.Socket.t()} | {:error, map()}", - "input_strings": [ - "binary()", - "payload()", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:ok, Phoenix.Socket.t()}", - "{:ok, payload(), Phoenix.Socket.t()}", - "{:error, map()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 392, - "name": "handle_out", - "clauses": [ - { - "full": "@callback handle_out(String.t(), payload(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t(), timeout() | :hibernate} | {:stop, term(), Phoenix.Socket.t()}", - "input_strings": [ - "String.t()", - "payload()", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:noreply, Phoenix.Socket.t()}", - "{:noreply, Phoenix.Socket.t(), timeout()", - ":hibernate}", - "{:stop, term(), Phoenix.Socket.t()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 402, - "name": "handle_info", - "clauses": [ - { - "full": "@callback handle_info(term(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", - "input_strings": [ - "term()", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:noreply, Phoenix.Socket.t()}", - "{:stop, term(), Phoenix.Socket.t()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 380, - "name": "handle_in", - "clauses": [ - { - "full": "@callback handle_in(String.t(), payload(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t(), timeout() | :hibernate} | {:reply, reply(), Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()} | {:stop, term(), reply(), Phoenix.Socket.t()}", - "input_strings": [ - "String.t()", - "payload()", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:noreply, Phoenix.Socket.t()}", - "{:noreply, Phoenix.Socket.t(), timeout()", - ":hibernate}", - "{:reply, reply(), Phoenix.Socket.t()}", - "{:stop, term(), Phoenix.Socket.t()}", - "{:stop, term(), reply(), Phoenix.Socket.t()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 421, - "name": "handle_cast", - "clauses": [ - { - "full": "@callback handle_cast(term(), Phoenix.Socket.t()) :: {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", - "input_strings": [ - "term()", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:noreply, Phoenix.Socket.t()}", - "{:stop, term(), Phoenix.Socket.t()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 411, - "name": "handle_call", - "clauses": [ - { - "full": "@callback handle_call(term(), {pid(), term()}, Phoenix.Socket.t()) :: {:reply, term(), Phoenix.Socket.t()} | {:noreply, Phoenix.Socket.t()} | {:stop, term(), Phoenix.Socket.t()}", - "input_strings": [ - "term()", - "{pid(), term()}", - "Phoenix.Socket.t()" - ], - "return_strings": [ - "{:reply, term(), Phoenix.Socket.t()}", - "{:noreply, Phoenix.Socket.t()}", - "{:stop, term(), Phoenix.Socket.t()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 426, - "name": "code_change", - "clauses": [ - { - "full": "@callback code_change(old_vsn, Phoenix.Socket.t(), term()) :: {:ok, Phoenix.Socket.t()} | {:error, term()}", - "input_strings": [ - "old_vsn", - "Phoenix.Socket.t()", - "term()" - ], - "return_strings": [ - "{:ok, Phoenix.Socket.t()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 687, - "name": "socket_ref", - "clauses": [ - { - "full": "@spec socket_ref(Phoenix.Socket.t()) :: socket_ref()", - "input_strings": [ - "Phoenix.Socket.t()" - ], - "return_strings": [ - "socket_ref()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 673, - "name": "reply", - "clauses": [ - { - "full": "@spec reply(socket_ref(), reply()) :: :ok", - "input_strings": [ - "socket_ref()", - "reply()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Channel.Server": [ - { - "arity": 1, - "line": 65, - "name": "socket", - "clauses": [ - { - "full": "@spec socket(pid()) :: Phoenix.Socket.t()", - "input_strings": [ - "pid()" - ], - "return_strings": [ - "Phoenix.Socket.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 4, - "line": 16, - "name": "join", - "clauses": [ - { - "full": "@spec join(Phoenix.Socket.t(), module(), Phoenix.Socket.Message.t(), elixir.keyword()) :: {:ok, term(), pid()} | {:error, term()}", - "input_strings": [ - "Phoenix.Socket.t()", - "module()", - "Phoenix.Socket.Message.t()", - "elixir.keyword()" - ], - "return_strings": [ - "{:ok, term(), pid()}", - "{:error, term()}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 75, - "name": "close", - "clauses": [ - { - "full": "@spec close(pid(), timeout()) :: :ok", - "input_strings": [ - "pid()", - "timeout()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.PoolDrainer": [ - { - "arity": 1, - "line": 66, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Controller": [ - { - "arity": 1, - "line": 346, - "name": "view_template", - "clauses": [ - { - "full": "@spec view_template(Plug.Conn.t()) :: binary() | nil", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "binary()", - "nil" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 602, - "name": "view_module", - "clauses": [ - { - "full": "@spec view_module(Plug.Conn.t(), binary() | nil) :: atom()", - "input_strings": [ - "Plug.Conn.t()", - "binary() | nil" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 454, - "name": "text", - "clauses": [ - { - "full": "@spec text(Plug.Conn.t(), String.Chars.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "String.Chars.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 1333, - "name": "scrub_params", - "clauses": [ - { - "full": "@spec scrub_params(Plug.Conn.t(), String.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "String.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 333, - "name": "router_module", - "clauses": [ - { - "full": "@spec router_module(Plug.Conn.t()) :: atom()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 847, - "name": "root_layout", - "clauses": [ - { - "full": "@spec root_layout(Plug.Conn.t(), binary() | nil) :: {atom(), String.t() | atom()} | false", - "input_strings": [ - "Plug.Conn.t()", - "binary() | nil" - ], - "return_strings": [ - "{atom(), String.t()", - "atom()}", - "false" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 943, - "name": "render", - "clauses": [ - { - "full": "@spec render(Plug.Conn.t(), binary() | atom(), Keyword.t() | map()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "binary() | atom()", - "Keyword.t() | map()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 869, - "name": "render", - "clauses": [ - { - "full": "@spec render(Plug.Conn.t(), Keyword.t() | map() | binary() | atom()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "Keyword.t() | map() | binary() | atom()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 1618, - "name": "refuse", - "clauses": [ - { - "full": "@spec refuse(term(), [tuple()], [binary()]) :: no_return()", - "input_strings": [ - "term()", - "[tuple()]", - "[binary()]" - ], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 520, - "name": "raise_invalid_url", - "clauses": [ - { - "full": "@spec raise_invalid_url(term()) :: no_return()", - "input_strings": [ - "term()" - ], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 535, - "name": "put_view", - "clauses": [ - { - "full": "@spec put_view(Plug.Conn.t(), [{atom(), view()}] | view()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[{atom(), view()}] | view()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 790, - "name": "put_root_layout", - "clauses": [ - { - "full": "@spec put_root_layout(Plug.Conn.t(), [{atom(), layout()}] | false) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[{atom(), layout()}] | false" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 581, - "name": "put_new_view", - "clauses": [ - { - "full": "@spec put_new_view(Plug.Conn.t(), [{atom(), view()}] | view()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[{atom(), view()}] | view()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 742, - "name": "put_new_layout", - "clauses": [ - { - "full": "@spec put_new_layout(Plug.Conn.t(), [{atom(), layout()}] | layout()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[{atom(), layout()}] | layout()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 809, - "name": "put_layout_formats", - "clauses": [ - { - "full": "@spec put_layout_formats(Plug.Conn.t(), [String.t()]) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[String.t()]" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 649, - "name": "put_layout", - "clauses": [ - { - "full": "@spec put_layout(Plug.Conn.t(), [{atom(), layout()}] | false) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[{atom(), layout()}] | false" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 827, - "name": "layout_formats", - "clauses": [ - { - "full": "@spec layout_formats(Plug.Conn.t()) :: [String.t()]", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "[String.t()]" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 837, - "name": "layout", - "clauses": [ - { - "full": "@spec layout(Plug.Conn.t(), binary() | nil) :: {atom(), String.t() | atom()} | false", - "input_strings": [ - "Plug.Conn.t()", - "binary() | nil" - ], - "return_strings": [ - "{atom(), String.t()", - "atom()}", - "false" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 362, - "name": "json", - "clauses": [ - { - "full": "@spec json(Plug.Conn.t(), term()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "term()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 467, - "name": "html", - "clauses": [ - { - "full": "@spec html(Plug.Conn.t(), iodata()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "iodata()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 339, - "name": "endpoint_module", - "clauses": [ - { - "full": "@spec endpoint_module(Plug.Conn.t()) :: atom()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 327, - "name": "controller_module", - "clauses": [ - { - "full": "@spec controller_module(Plug.Conn.t()) :: atom()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 391, - "name": "allow_jsonp", - "clauses": [ - { - "full": "@spec allow_jsonp(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "Keyword.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 321, - "name": "action_name", - "clauses": [ - { - "full": "@spec action_name(Plug.Conn.t()) :: atom()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 1520, - "name": "accepts", - "clauses": [ - { - "full": "@spec accepts(Plug.Conn.t(), [binary()]) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[binary()]" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.Float": [ - { - "arity": 1, - "line": 70, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Float", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Float" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 70, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint.Watcher": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Socket": [ - { - "arity": 0, - "line": 81, - "name": "raise_with_help", - "clauses": [ - { - "full": "@spec raise_with_help() :: no_return()", - "input_strings": [], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.NoRouteError": [ - { - "arity": 1, - "line": 2, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.Helpers": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.CodeReloader.Proxy": [ - { - "arity": 1, - "line": 3, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.ActionClauseError": [ - { - "arity": 1, - "line": 41, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket": [ - { - "arity": 1, - "line": 246, - "name": "id", - "clauses": [ - { - "full": "@callback id(t()) :: String.t() | nil", - "input_strings": [ - "t()" - ], - "return_strings": [ - "String.t()", - "nil" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 222, - "name": "connect", - "clauses": [ - { - "full": "@callback connect(map(), t(), map()) :: {:ok, t()} | {:error, term()} | :error", - "input_strings": [ - "map()", - "t()", - "map()" - ], - "return_strings": [ - "{:ok, t()}", - "{:error, term()}", - ":error" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 230, - "name": "connect", - "clauses": [ - { - "full": "@callback connect(map(), t()) :: {:ok, t()} | {:error, term()} | :error", - "input_strings": [ - "map()", - "t()" - ], - "return_strings": [ - "{:ok, t()}", - "{:error, term()}", - ":error" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Digester.Gzip": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Channel": [ - { - "arity": 0, - "line": 96, - "name": "raise_with_help", - "clauses": [ - { - "full": "@spec raise_with_help() :: no_return()", - "input_strings": [], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.Transport": [ - { - "arity": 2, - "line": 245, - "name": "terminate", - "clauses": [ - { - "full": "@callback terminate(term(), state()) :: :ok", - "input_strings": [ - "term()", - "state()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 174, - "name": "init", - "clauses": [ - { - "full": "@callback init(state()) :: {:ok, state()}", - "input_strings": [ - "state()" - ], - "return_strings": [ - "{:ok, state()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 233, - "name": "handle_info", - "clauses": [ - { - "full": "@callback handle_info(term(), state()) :: {:ok, state()} | {:push, {atom(), term()}, state()} | {:stop, term(), state()}", - "input_strings": [ - "term()", - "state()" - ], - "return_strings": [ - "{:ok, state()}", - "{:push, {atom(), term()}, state()}", - "{:stop, term(), state()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 191, - "name": "handle_in", - "clauses": [ - { - "full": "@callback handle_in({term(), elixir.keyword()}, state()) :: {:ok, state()} | {:reply, :ok | :error, {atom(), term()}, state()} | {:stop, term(), state()}", - "input_strings": [ - "{term(), elixir.keyword()}", - "state()" - ], - "return_strings": [ - "{:ok, state()}", - "{:reply, :ok", - ":error, {atom(), term()}, state()}", - "{:stop, term(), state()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 214, - "name": "handle_control", - "clauses": [ - { - "full": "@callback handle_control({term(), elixir.keyword()}, state()) :: {:ok, state()} | {:reply, :ok | :error, {atom(), term()}, state()} | {:stop, term(), state()}", - "input_strings": [ - "{term(), elixir.keyword()}", - "state()" - ], - "return_strings": [ - "{:ok, state()}", - "{:reply, :ok", - ":error, {atom(), term()}, state()}", - "{:stop, term(), state()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 137, - "name": "drainer_spec", - "clauses": [ - { - "full": "@callback drainer_spec(elixir.keyword()) :: supervisor.child_spec() | :ignore", - "input_strings": [ - "elixir.keyword()" - ], - "return_strings": [ - "supervisor.child_spec()", - ":ignore" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 166, - "name": "connect", - "clauses": [ - { - "full": "@callback connect(map()) :: {:ok, state()} | {:error, term()} | :error", - "input_strings": [ - "map()" - ], - "return_strings": [ - "{:ok, state()}", - "{:error, term()}", - ":error" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 125, - "name": "child_spec", - "clauses": [ - { - "full": "@callback child_spec(elixir.keyword()) :: supervisor.child_spec() | :ignore", - "input_strings": [ - "elixir.keyword()" - ], - "return_strings": [ - "supervisor.child_spec()", - ":ignore" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Naming": [ - { - "arity": 2, - "line": 40, - "name": "unsuffix", - "clauses": [ - { - "full": "@spec unsuffix(String.t(), String.t()) :: String.t()", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 66, - "name": "underscore", - "clauses": [ - { - "full": "@spec underscore(String.t()) :: String.t()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 18, - "name": "resource_name", - "clauses": [ - { - "full": "@spec resource_name(String.Chars.t(), String.t()) :: String.t()", - "input_strings": [ - "String.Chars.t()", - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 119, - "name": "humanize", - "clauses": [ - { - "full": "@spec humanize(atom() | String.t()) :: String.t()", - "input_strings": [ - "atom() | String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 96, - "name": "camelize", - "clauses": [ - { - "full": "@spec camelize(String.t(), :lower) :: String.t()", - "input_strings": [ - "String.t()", - ":lower" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 93, - "name": "camelize", - "clauses": [ - { - "full": "@spec camelize(String.t()) :: String.t()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Flash": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param": [ - { - "arity": 1, - "line": 62, - "name": "to_param", - "clauses": [ - { - "full": "@callback to_param(term()) :: String.t()", - "input_strings": [ - "term()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 62, - "name": "to_param", - "clauses": [ - { - "full": "@spec to_param(term()) :: String.t()", - "input_strings": [ - "term()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "impl_for!", - "clauses": [ - { - "full": "@spec impl_for!(term()) :: atom()", - "input_strings": [ - "term()" - ], - "return_strings": [ - "atom()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "impl_for", - "clauses": [ - { - "full": "@spec impl_for(term()) :: atom() | nil", - "input_strings": [ - "term()" - ], - "return_strings": [ - "atom()", - "nil" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__protocol__", - "clauses": [ - { - "full": "@spec __protocol__(:module) :: Phoenix.Param", - "input_strings": [ - ":module" - ], - "return_strings": [ - "Phoenix.Param" - ] - }, - { - "full": "@spec __protocol__(:functions) :: [{atom(), arity()}]", - "input_strings": [ - ":functions" - ], - "return_strings": [ - "[{atom(), arity()}]" - ] - }, - { - "full": "@spec __protocol__(:consolidated?) :: boolean()", - "input_strings": [ - ":consolidated?" - ], - "return_strings": [ - "boolean()" - ] - }, - { - "full": "@spec __protocol__(:impls) :: :not_consolidated | {:consolidated, [module()]}", - "input_strings": [ - ":impls" - ], - "return_strings": [ - ":not_consolidated", - "{:consolidated, [module()]}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Embedded": [ - { - "arity": 1, - "line": 80, - "name": "raise_with_help", - "clauses": [ - { - "full": "@spec raise_with_help(String.t()) :: no_return()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Schema": [ - { - "arity": 1, - "line": 276, - "name": "raise_with_help", - "clauses": [ - { - "full": "@spec raise_with_help(String.t()) :: no_return()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.Serializer": [ - { - "arity": 1, - "line": 14, - "name": "fastlane!", - "clauses": [ - { - "full": "@callback fastlane!(Phoenix.Socket.Broadcast.t()) :: {:socket_push, :text, iodata()} | {:socket_push, :binary, iodata()}", - "input_strings": [ - "Phoenix.Socket.Broadcast.t()" - ], - "return_strings": [ - "{:socket_push, :text, iodata()}", - "{:socket_push, :binary, iodata()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 21, - "name": "encode!", - "clauses": [ - { - "full": "@callback encode!(Phoenix.Socket.Message.t() | Phoenix.Socket.Reply.t()) :: {:socket_push, :text, iodata()} | {:socket_push, :binary, iodata()}", - "input_strings": [ - "Phoenix.Socket.Message.t() | Phoenix.Socket.Reply.t()" - ], - "return_strings": [ - "{:socket_push, :text, iodata()}", - "{:socket_push, :binary, iodata()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 28, - "name": "decode!", - "clauses": [ - { - "full": "@callback decode!(iodata(), Keyword.t()) :: Phoenix.Socket.Message.t()", - "input_strings": [ - "iodata()", - "Keyword.t()" - ], - "return_strings": [ - "Phoenix.Socket.Message.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Digest": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Html": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.Integer": [ - { - "arity": 1, - "line": 66, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Integer", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Integer" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 66, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint": [ - { - "arity": 0, - "line": 313, - "name": "url", - "clauses": [ - { - "full": "@callback url() :: String.t()", - "input_strings": [], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 371, - "name": "unsubscribe", - "clauses": [ - { - "full": "@callback unsubscribe(topic()) :: :ok | {:error, term()}", - "input_strings": [ - "topic()" - ], - "return_strings": [ - ":ok", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 366, - "name": "subscribe", - "clauses": [ - { - "full": "@callback subscribe(topic(), Keyword.t()) :: :ok | {:error, term()}", - "input_strings": [ - "topic()", - "Keyword.t()" - ], - "return_strings": [ - ":ok", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 0, - "line": 308, - "name": "struct_url", - "clauses": [ - { - "full": "@callback struct_url() :: URI.t()", - "input_strings": [], - "return_strings": [ - "URI.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 0, - "line": 323, - "name": "static_url", - "clauses": [ - { - "full": "@callback static_url() :: String.t()", - "input_strings": [], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 328, - "name": "static_path", - "clauses": [ - { - "full": "@callback static_path(String.t()) :: String.t()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 338, - "name": "static_lookup", - "clauses": [ - { - "full": "@callback static_lookup(String.t()) :: {String.t(), String.t()} | {String.t(), nil}", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "{String.t(), String.t()}", - "{String.t(), nil}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 333, - "name": "static_integrity", - "clauses": [ - { - "full": "@callback static_integrity(String.t()) :: String.t() | nil", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()", - "nil" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 291, - "name": "start_link", - "clauses": [ - { - "full": "@callback start_link(elixir.keyword()) :: Supervisor.on_start()", - "input_strings": [ - "elixir.keyword()" - ], - "return_strings": [ - "Supervisor.on_start()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 355, - "name": "server_info", - "clauses": [ - { - "full": "@callback server_info(Plug.Conn.scheme()) :: {:ok, {inet.ip_address(), inet.port_number()} | inet.returned_non_ip_address()} | {:error, term()}", - "input_strings": [ - "Plug.Conn.scheme()" - ], - "return_strings": [ - "{:ok, {inet.ip_address(), inet.port_number()}", - "inet.returned_non_ip_address()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 0, - "line": 343, - "name": "script_name", - "clauses": [ - { - "full": "@callback script_name() :: [String.t()]", - "input_strings": [], - "return_strings": [ - "[String.t()]" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 318, - "name": "path", - "clauses": [ - { - "full": "@callback path(String.t()) :: String.t()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 4, - "line": 405, - "name": "local_broadcast_from", - "clauses": [ - { - "full": "@callback local_broadcast_from(pid(), topic(), event(), msg()) :: :ok", - "input_strings": [ - "pid()", - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 400, - "name": "local_broadcast", - "clauses": [ - { - "full": "@callback local_broadcast(topic(), event(), msg()) :: :ok", - "input_strings": [ - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 0, - "line": 348, - "name": "host", - "clauses": [ - { - "full": "@callback host() :: String.t()", - "input_strings": [], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 301, - "name": "config_change", - "clauses": [ - { - "full": "@callback config_change(term(), term()) :: term()", - "input_strings": [ - "term()", - "term()" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 296, - "name": "config", - "clauses": [ - { - "full": "@callback config(atom(), term()) :: term()", - "input_strings": [ - "atom()", - "term()" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 4, - "line": 395, - "name": "broadcast_from!", - "clauses": [ - { - "full": "@callback broadcast_from!(pid(), topic(), event(), msg()) :: :ok", - "input_strings": [ - "pid()", - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 4, - "line": 388, - "name": "broadcast_from", - "clauses": [ - { - "full": "@callback broadcast_from(pid(), topic(), event(), msg()) :: :ok | {:error, term()}", - "input_strings": [ - "pid()", - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 383, - "name": "broadcast!", - "clauses": [ - { - "full": "@callback broadcast!(topic(), event(), msg()) :: :ok", - "input_strings": [ - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 376, - "name": "broadcast", - "clauses": [ - { - "full": "@callback broadcast(topic(), event(), msg()) :: :ok | {:error, term()}", - "input_strings": [ - "topic()", - "event()", - "msg()" - ], - "return_strings": [ - ":ok", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.CodeReloader.Server": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Phoenix.Scope": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.Atom": [ - { - "arity": 1, - "line": 78, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Atom", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Atom" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 78, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.Map": [ - { - "arity": 1, - "line": 88, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Map", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Map" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 88, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Transports.LongPoll.Server": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Plug.Exception.Phoenix.ActionClauseError": [ - { - "arity": 1, - "line": 69, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Phoenix.ActionClauseError", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Phoenix.ActionClauseError" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Plug.Exception", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Plug.Exception" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 69, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.NotAcceptableError": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Release": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint.SyncCodeReloadPlug": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.Any": [ - { - "arity": 1, - "line": 95, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Any", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Any" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 95, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.Reply": [ - { - "arity": 1, - "line": 53, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.ChannelTest": [ - { - "arity": 3, - "line": 471, - "name": "push", - "clauses": [ - { - "full": "@spec push(Phoenix.Socket.t(), String.t(), map()) :: reference()", - "input_strings": [ - "Phoenix.Socket.t()", - "String.t()", - "map()" - ], - "return_strings": [ - "reference()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 486, - "name": "leave", - "clauses": [ - { - "full": "@spec leave(Phoenix.Socket.t()) :: reference()", - "input_strings": [ - "Phoenix.Socket.t()" - ], - "return_strings": [ - "reference()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Transports.LongPoll": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint.Supervisor": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Secret": [ - { - "arity": 0, - "line": 32, - "name": "invalid_args!", - "clauses": [ - { - "full": "@spec invalid_args!() :: no_return()", - "input_strings": [], - "return_strings": [ - "no_return()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.ChannelTest.NoopSerializer": [ - { - "arity": 1, - "line": 159, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Presence": [ - { - "arity": 4, - "line": 272, - "name": "update", - "clauses": [ - { - "full": "@callback update(pid(), topic(), String.t(), map() | (map() -> map())) :: {:ok, binary()} | {:error, term()}", - "input_strings": [ - "pid()", - "topic()", - "String.t()", - "map() | (map() -> map())" - ], - "return_strings": [ - "{:ok, binary()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 259, - "name": "update", - "clauses": [ - { - "full": "@callback update(Phoenix.Socket.t(), String.t(), map() | (map() -> map())) :: {:ok, binary()} | {:error, term()}", - "input_strings": [ - "Phoenix.Socket.t()", - "String.t()", - "map() | (map() -> map())" - ], - "return_strings": [ - "{:ok, binary()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 251, - "name": "untrack", - "clauses": [ - { - "full": "@callback untrack(pid(), topic(), String.t()) :: :ok", - "input_strings": [ - "pid()", - "topic()", - "String.t()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 246, - "name": "untrack", - "clauses": [ - { - "full": "@callback untrack(Phoenix.Socket.t(), String.t()) :: :ok", - "input_strings": [ - "Phoenix.Socket.t()", - "String.t()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "callback" - }, - { - "arity": 4, - "line": 239, - "name": "track", - "clauses": [ - { - "full": "@callback track(pid(), topic(), String.t(), map()) :: {:ok, binary()} | {:error, term()}", - "input_strings": [ - "pid()", - "topic()", - "String.t()", - "map()" - ], - "return_strings": [ - "{:ok, binary()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 3, - "line": 230, - "name": "track", - "clauses": [ - { - "full": "@callback track(Phoenix.Socket.t(), String.t(), map()) :: {:ok, binary()} | {:error, term()}", - "input_strings": [ - "Phoenix.Socket.t()", - "String.t()", - "map()" - ], - "return_strings": [ - "{:ok, binary()}", - "{:error, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 302, - "name": "list", - "clauses": [ - { - "full": "@callback list(Phoenix.Socket.t() | topic()) :: presences()", - "input_strings": [ - "Phoenix.Socket.t() | topic()" - ], - "return_strings": [ - "presences()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 357, - "name": "init", - "clauses": [ - { - "full": "@callback init(term()) :: {:ok, term()}", - "input_strings": [ - "term()" - ], - "return_strings": [ - "{:ok, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 4, - "line": 362, - "name": "handle_metas", - "clauses": [ - { - "full": "@callback handle_metas(String.t(), map(), map(), term()) :: {:ok, term()}", - "input_strings": [ - "String.t()", - "map()", - "map()", - "term()" - ], - "return_strings": [ - "{:ok, term()}" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 320, - "name": "get_by_key", - "clauses": [ - { - "full": "@callback get_by_key(Phoenix.Socket.t() | topic(), String.t()) :: [presence()]", - "input_strings": [ - "Phoenix.Socket.t() | topic()", - "String.t()" - ], - "return_strings": [ - "[presence()]" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 349, - "name": "fetch", - "clauses": [ - { - "full": "@callback fetch(topic(), presences()) :: presences()", - "input_strings": [ - "topic()", - "presences()" - ], - "return_strings": [ - "presences()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint.RenderErrors": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Phoenix.Schema": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Debug": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.V2.JSONSerializer": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.MissingParamError": [ - { - "arity": 1, - "line": 18, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Inspect.Phoenix.Socket.Message": [ - { - "arity": 1, - "line": 39, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: Phoenix.Socket.Message", - "input_strings": [ - ":for" - ], - "return_strings": [ - "Phoenix.Socket.Message" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Inspect", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Inspect" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 39, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.CodeReloader": [ - { - "arity": 0, - "line": 70, - "name": "sync", - "clauses": [ - { - "full": "@spec sync() :: :ok", - "input_strings": [], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 62, - "name": "reload!", - "clauses": [ - { - "full": "@spec reload!(module(), elixir.keyword()) :: :ok | {:error, binary()}", - "input_strings": [ - "module()", - "elixir.keyword()" - ], - "return_strings": [ - ":ok", - "{:error, binary()}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 54, - "name": "reload", - "clauses": [ - { - "full": "@spec reload(module(), elixir.keyword()) :: :ok | {:error, binary()}", - "input_strings": [ - "module()", - "elixir.keyword()" - ], - "return_strings": [ - ":ok", - "{:error, binary()}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 74, - "name": "child_spec", - "clauses": [ - { - "full": "@spec child_spec(elixir.keyword()) :: Supervisor.child_spec()", - "input_strings": [ - "elixir.keyword()" - ], - "return_strings": [ - "Supervisor.child_spec()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.InvalidMessageError": [ - { - "arity": 1, - "line": 250, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.V1.JSONSerializer": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.Message": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Controller.Pipeline": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Server": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Routes": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.ConnTest": [ - { - "arity": 2, - "line": 400, - "name": "text_response", - "clauses": [ - { - "full": "@spec text_response(Plug.Conn.t(), integer() | atom()) :: String.t()", - "input_strings": [ - "Plug.Conn.t()", - "integer() | atom()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 310, - "name": "response_content_type", - "clauses": [ - { - "full": "@spec response_content_type(Plug.Conn.t(), atom()) :: String.t()", - "input_strings": [ - "Plug.Conn.t()", - "atom()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 356, - "name": "response", - "clauses": [ - { - "full": "@spec response(Plug.Conn.t(), integer() | atom()) :: binary()", - "input_strings": [ - "Plug.Conn.t()", - "integer() | atom()" - ], - "return_strings": [ - "binary()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 437, - "name": "redirected_to", - "clauses": [ - { - "full": "@spec redirected_to(Plug.Conn.t(), non_neg_integer()) :: String.t()", - "input_strings": [ - "Plug.Conn.t()", - "non_neg_integer()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 589, - "name": "redirected_params", - "clauses": [ - { - "full": "@spec redirected_params(Plug.Conn.t(), non_neg_integer()) :: map()", - "input_strings": [ - "Plug.Conn.t()", - "non_neg_integer()" - ], - "return_strings": [ - "map()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 475, - "name": "recycle", - "clauses": [ - { - "full": "@spec recycle(Plug.Conn.t(), [String.t()]) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "[String.t()]" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 258, - "name": "put_req_cookie", - "clauses": [ - { - "full": "@spec put_req_cookie(Plug.Conn.t(), binary(), binary()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "binary()", - "binary()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 292, - "name": "put_flash", - "clauses": [ - { - "full": "@spec put_flash(Plug.Conn.t(), term(), term()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "term()", - "term()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 625, - "name": "path_params", - "clauses": [ - { - "full": "@spec path_params(Plug.Conn.t(), String.t()) :: map()", - "input_strings": [ - "Plug.Conn.t()", - "String.t()" - ], - "return_strings": [ - "map()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 417, - "name": "json_response", - "clauses": [ - { - "full": "@spec json_response(Plug.Conn.t(), integer() | atom()) :: term()", - "input_strings": [ - "Plug.Conn.t()", - "integer() | atom()" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 252, - "name": "init_test_session", - "clauses": [ - { - "full": "@spec init_test_session(Plug.Conn.t(), map() | elixir.keyword()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "map() | elixir.keyword()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 385, - "name": "html_response", - "clauses": [ - { - "full": "@spec html_response(Plug.Conn.t(), integer() | atom()) :: String.t()", - "input_strings": [ - "Plug.Conn.t()", - "integer() | atom()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 283, - "name": "get_flash", - "clauses": [ - { - "full": "@spec get_flash(Plug.Conn.t(), term()) :: term()", - "input_strings": [ - "Plug.Conn.t()", - "term()" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 276, - "name": "get_flash", - "clauses": [ - { - "full": "@spec get_flash(Plug.Conn.t()) :: map()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "map()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 270, - "name": "fetch_flash", - "clauses": [ - { - "full": "@spec fetch_flash(Plug.Conn.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 495, - "name": "ensure_recycled", - "clauses": [ - { - "full": "@spec ensure_recycled(Plug.Conn.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 264, - "name": "delete_req_cookie", - "clauses": [ - { - "full": "@spec delete_req_cookie(Plug.Conn.t(), binary()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "binary()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 298, - "name": "clear_flash", - "clauses": [ - { - "full": "@spec clear_flash(Plug.Conn.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 571, - "name": "bypass_through", - "clauses": [ - { - "full": "@spec bypass_through(Plug.Conn.t(), module(), atom() | list()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "module()", - "atom() | list()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 561, - "name": "bypass_through", - "clauses": [ - { - "full": "@spec bypass_through(Plug.Conn.t(), module()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()", - "module()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 551, - "name": "bypass_through", - "clauses": [ - { - "full": "@spec bypass_through(Plug.Conn.t()) :: Plug.Conn.t()", - "input_strings": [ - "Plug.Conn.t()" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 150, - "name": "build_conn", - "clauses": [ - { - "full": "@spec build_conn(atom() | binary(), binary(), binary() | list() | map() | nil) :: Plug.Conn.t()", - "input_strings": [ - "atom() | binary()", - "binary()", - "binary() | list() | map() | nil" - ], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 0, - "line": 138, - "name": "build_conn", - "clauses": [ - { - "full": "@spec build_conn() :: Plug.Conn.t()", - "input_strings": [], - "return_strings": [ - "Plug.Conn.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 676, - "name": "assert_error_sent", - "clauses": [ - { - "full": "@spec assert_error_sent(integer() | atom(), function()) :: {integer(), list(), term()}", - "input_strings": [ - "integer() | atom()", - "function()" - ], - "return_strings": [ - "{integer(), list(), term()}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Live": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.Broadcast": [ - { - "arity": 1, - "line": 71, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.MalformedURIError": [ - { - "arity": 1, - "line": 21, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Presence.Tracker": [ - { - "arity": 1, - "line": 427, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Transports.WebSocket": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.ConsoleFormatter": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Compile.Phoenix": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Socket.PoolSupervisor": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Endpoint.Cowboy2Adapter": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Config": [ - { - "arity": 1, - "line": 78, - "name": "clear_cache", - "clauses": [ - { - "full": "@spec clear_cache(module()) :: :ok", - "input_strings": [ - "module()" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "spec" - }, - { - "arity": 3, - "line": 46, - "name": "cache", - "clauses": [ - { - "full": "@spec cache(module(), term(), (module() -> {:cache | :nocache, term()})) :: term()", - "input_strings": [ - "module()", - "term()", - "(module() -> {:cache | :nocache, term()})" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Digester.Compressor": [ - { - "arity": 0, - "line": 43, - "name": "file_extensions", - "clauses": [ - { - "full": "@callback file_extensions() :: nonempty_list(String.t())", - "input_strings": [], - "return_strings": [ - "nonempty_list(String.t())" - ] - } - ], - "kind": "callback" - }, - { - "arity": 2, - "line": 42, - "name": "compress_file", - "clauses": [ - { - "full": "@callback compress_file(Path.t(), binary()) :: {:ok, binary()} | :error", - "input_strings": [ - "Path.t()", - "binary()" - ], - "return_strings": [ - "{:ok, binary()}", - ":error" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Digester": [ - { - "arity": 3, - "line": 19, - "name": "compile", - "clauses": [ - { - "full": "@spec compile(String.t(), String.t(), boolean()) :: :ok | {:error, :invalid_path}", - "input_strings": [ - "String.t()", - "String.t()", - "boolean()" - ], - "return_strings": [ - ":ok", - "{:error, :invalid_path}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 355, - "name": "clean_all", - "clauses": [ - { - "full": "@spec clean_all(String.t()) :: :ok | {:error, :invalid_path}", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - ":ok", - "{:error, :invalid_path}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 4, - "line": 334, - "name": "clean", - "clauses": [ - { - "full": "@spec clean(String.t(), integer(), integer(), integer()) :: :ok | {:error, :invalid_path}", - "input_strings": [ - "String.t()", - "integer()", - "integer()", - "integer()" - ], - "return_strings": [ - ":ok", - "{:error, :invalid_path}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.CodeReloader.MixListener": [ - { - "arity": 0, - "line": 13, - "name": "started?", - "clauses": [ - { - "full": "@spec started?() :: boolean()", - "input_strings": [], - "return_strings": [ - "boolean()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 8, - "name": "start_link", - "clauses": [ - { - "full": "@spec start_link(elixir.keyword()) :: GenServer.on_start()", - "input_strings": [ - "elixir.keyword()" - ], - "return_strings": [ - "GenServer.on_start()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 23, - "name": "purge", - "clauses": [ - { - "full": "@spec purge([atom()]) :: :ok", - "input_strings": [ - "[atom()]" - ], - "return_strings": [ - ":ok" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.VerifiedRoutes": [ - { - "arity": 2, - "line": 295, - "name": "verified_route?", - "clauses": [ - { - "full": "@callback verified_route?(plug_opts(), [String.t()]) :: boolean()", - "input_strings": [ - "plug_opts()", - "[String.t()]" - ], - "return_strings": [ - "boolean()" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 287, - "name": "formatted_routes", - "clauses": [ - { - "full": "@callback formatted_routes(plug_opts()) :: [formatted_route()]", - "input_strings": [ - "plug_opts()" - ], - "return_strings": [ - "[formatted_route()]" - ] - } - ], - "kind": "callback" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Json": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Param.BitString": [ - { - "arity": 1, - "line": 74, - "name": "__impl__", - "clauses": [ - { - "full": "@spec __impl__(:for) :: BitString", - "input_strings": [ - ":for" - ], - "return_strings": [ - "BitString" - ] - }, - { - "full": "@spec __impl__(:protocol) :: Phoenix.Param", - "input_strings": [ - ":protocol" - ], - "return_strings": [ - "Phoenix.Param" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 74, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Phoenix": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Phoenix.Context": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Context": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Token": [ - { - "arity": 4, - "line": 218, - "name": "verify", - "clauses": [ - { - "full": "@spec verify(context(), binary(), binary(), [shared_opt() | max_age_opt()]) :: {:ok, term()} | {:error, :expired | :invalid | :missing}", - "input_strings": [ - "context()", - "binary()", - "binary()", - "[shared_opt() | max_age_opt()]" - ], - "return_strings": [ - "{:ok, term()}", - "{:error, :expired", - ":invalid", - ":missing}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 4, - "line": 132, - "name": "sign", - "clauses": [ - { - "full": "@spec sign(context(), binary(), term(), [shared_opt() | max_age_opt() | signed_at_opt()]) :: binary()", - "input_strings": [ - "context()", - "binary()", - "term()", - "[shared_opt() | max_age_opt() | signed_at_opt()]" - ], - "return_strings": [ - "binary()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 4, - "line": 158, - "name": "encrypt", - "clauses": [ - { - "full": "@spec encrypt(context(), binary(), term(), [shared_opt() | max_age_opt() | signed_at_opt()]) :: binary()", - "input_strings": [ - "context()", - "binary()", - "term()", - "[shared_opt() | max_age_opt() | signed_at_opt()]" - ], - "return_strings": [ - "binary()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 4, - "line": 243, - "name": "decrypt", - "clauses": [ - { - "full": "@spec decrypt(context(), binary(), binary(), [shared_opt() | max_age_opt()]) :: term()", - "input_strings": [ - "context()", - "binary()", - "binary()", - "[shared_opt() | max_age_opt()]" - ], - "return_strings": [ - "term()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.Scope": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.Route": [ - { - "arity": 14, - "line": 63, - "name": "build", - "clauses": [ - { - "full": "@spec build(non_neg_integer(), :match | :forward, atom(), String.t(), String.t() | nil, atom(), atom(), atom() | nil, [atom()], map(), map(), map(), boolean(), boolean()) :: t()", - "input_strings": [ - "non_neg_integer()", - ":match | :forward", - "atom()", - "String.t()", - "String.t() | nil", - "atom()", - "atom()", - "atom() | nil", - "[atom()]", - "map()", - "map()", - "map()", - "boolean()", - "boolean()" - ], - "return_strings": [ - "t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Auth": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Auth.Injector": [ - { - "arity": 2, - "line": 63, - "name": "test_config_inject", - "clauses": [ - { - "full": "@spec test_config_inject(String.t(), Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", - "input_strings": [ - "String.t()", - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()" - ], - "return_strings": [ - "{:ok, String.t()}", - ":already_injected", - "{:error, :unable_to_inject}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 77, - "name": "test_config_help_text", - "clauses": [ - { - "full": "@spec test_config_help_text(String.t(), Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()) :: String.t()", - "input_strings": [ - "String.t()", - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 291, - "name": "split_with_self", - "clauses": [ - { - "full": "@spec split_with_self(String.t(), String.t()) :: {String.t(), String.t(), String.t()} | :error", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "{String.t(), String.t(), String.t()}", - ":error" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 98, - "name": "router_plug_inject", - "clauses": [ - { - "full": "@spec router_plug_inject(String.t(), elixir.keyword()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", - "input_strings": [ - "String.t()", - "elixir.keyword()" - ], - "return_strings": [ - "{:ok, String.t()}", - ":already_injected", - "{:error, :unable_to_inject}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 120, - "name": "router_plug_help_text", - "clauses": [ - { - "full": "@spec router_plug_help_text(String.t(), elixir.keyword()) :: String.t()", - "input_strings": [ - "String.t()", - "elixir.keyword()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 299, - "name": "normalize_line_endings_to_file", - "clauses": [ - { - "full": "@spec normalize_line_endings_to_file(String.t(), String.t()) :: String.t()", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 12, - "name": "mix_dependency_inject", - "clauses": [ - { - "full": "@spec mix_dependency_inject(String.t(), String.t()) :: {:ok, String.t()} | :already_injected | {:error, :unable_to_inject}", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "{:ok, String.t()}", - ":already_injected", - "{:error, :unable_to_inject}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 265, - "name": "inject_before_final_end", - "clauses": [ - { - "full": "@spec inject_before_final_end(String.t(), String.t()) :: {:ok, String.t()} | :already_injected", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "{:ok, String.t()}", - ":already_injected" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 304, - "name": "get_line_ending", - "clauses": [ - { - "full": "@spec get_line_ending(String.t()) :: String.t()", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "String.t()" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 282, - "name": "ensure_not_already_injected", - "clauses": [ - { - "full": "@spec ensure_not_already_injected(String.t(), String.t()) :: :ok | :already_injected", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - ":ok", - ":already_injected" - ] - } - ], - "kind": "spec" - }, - { - "arity": 2, - "line": 21, - "name": "do_mix_dependency_inject", - "clauses": [ - { - "full": "@spec do_mix_dependency_inject(String.t(), String.t()) :: {:ok, String.t()} | {:error, :unable_to_inject}", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "{:ok, String.t()}", - "{:error, :unable_to_inject}" - ] - } - ], - "kind": "spec" - }, - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Phoenix.Router.Resource": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Cert": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Auth.Migration": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Gen.Presence": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ], - "Mix.Tasks.Phx.Digest.Clean": [ - { - "arity": 1, - "line": 1, - "name": "__info__", - "clauses": [ - { - "full": "@spec __info__(:attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct) :: any()", - "input_strings": [ - ":attributes | :compile | :functions | :macros | :md5 | :exports_md5 | :module | :deprecated | :struct" - ], - "return_strings": [ - "any()" - ] - } - ], - "kind": "spec" - } - ] - }, - "structs": { - "Mix.Phoenix.Context": { - "fields": [ - { - "default": "nil", - "field": "name", - "required": false - }, - { - "default": "nil", - "field": "module", - "required": false - }, - { - "default": "nil", - "field": "schema", - "required": false - }, - { - "default": "nil", - "field": "alias", - "required": false - }, - { - "default": "nil", - "field": "base_module", - "required": false - }, - { - "default": "nil", - "field": "web_module", - "required": false - }, - { - "default": "nil", - "field": "basename", - "required": false - }, - { - "default": "nil", - "field": "file", - "required": false - }, - { - "default": "nil", - "field": "test_file", - "required": false - }, - { - "default": "nil", - "field": "test_fixtures_file", - "required": false - }, - { - "default": "nil", - "field": "dir", - "required": false - }, - { - "default": "true", - "field": "generate?", - "required": false - }, - { - "default": "nil", - "field": "context_app", - "required": false - }, - { - "default": "[]", - "field": "opts", - "required": false - }, - { - "default": "nil", - "field": "scope", - "required": false - } - ] - }, - "Mix.Phoenix.Schema": { - "fields": [ - { - "default": "nil", - "field": "module", - "required": false - }, - { - "default": "nil", - "field": "repo", - "required": false - }, - { - "default": "nil", - "field": "repo_alias", - "required": false - }, - { - "default": "nil", - "field": "table", - "required": false - }, - { - "default": "nil", - "field": "collection", - "required": false - }, - { - "default": "false", - "field": "embedded?", - "required": false - }, - { - "default": "true", - "field": "generate?", - "required": false - }, - { - "default": "[]", - "field": "opts", - "required": false - }, - { - "default": "nil", - "field": "alias", - "required": false - }, - { - "default": "nil", - "field": "file", - "required": false - }, - { - "default": "[]", - "field": "attrs", - "required": false - }, - { - "default": "nil", - "field": "string_attr", - "required": false - }, - { - "default": "nil", - "field": "plural", - "required": false - }, - { - "default": "nil", - "field": "singular", - "required": false - }, - { - "default": "[]", - "field": "uniques", - "required": false - }, - { - "default": "[]", - "field": "redacts", - "required": false - }, - { - "default": "[]", - "field": "assocs", - "required": false - }, - { - "default": "[]", - "field": "types", - "required": false - }, - { - "default": "[]", - "field": "indexes", - "required": false - }, - { - "default": "[]", - "field": "defaults", - "required": false - }, - { - "default": "nil", - "field": "human_singular", - "required": false - }, - { - "default": "nil", - "field": "human_plural", - "required": false - }, - { - "default": "false", - "field": "binary_id", - "required": false - }, - { - "default": "nil", - "field": "migration_defaults", - "required": false - }, - { - "default": "false", - "field": "migration?", - "required": false - }, - { - "default": "%{}", - "field": "params", - "required": false - }, - { - "default": "[]", - "field": "optionals", - "required": false - }, - { - "default": "nil", - "field": "sample_id", - "required": false - }, - { - "default": "nil", - "field": "web_path", - "required": false - }, - { - "default": "nil", - "field": "web_namespace", - "required": false - }, - { - "default": "nil", - "field": "context_app", - "required": false - }, - { - "default": "nil", - "field": "route_helper", - "required": false - }, - { - "default": "nil", - "field": "route_prefix", - "required": false - }, - { - "default": "nil", - "field": "api_route_prefix", - "required": false - }, - { - "default": "nil", - "field": "migration_module", - "required": false - }, - { - "default": "[]", - "field": "fixture_unique_functions", - "required": false - }, - { - "default": "[]", - "field": "fixture_params", - "required": false - }, - { - "default": "nil", - "field": "prefix", - "required": false - }, - { - "default": ":naive_datetime", - "field": "timestamp_type", - "required": false - }, - { - "default": "nil", - "field": "scope", - "required": false - } - ] - }, - "Mix.Phoenix.Scope": { - "fields": [ - { - "default": "nil", - "field": "name", - "required": false - }, - { - "default": "false", - "field": "default", - "required": false - }, - { - "default": "nil", - "field": "module", - "required": false - }, - { - "default": "nil", - "field": "alias", - "required": false - }, - { - "default": "nil", - "field": "assign_key", - "required": false - }, - { - "default": "nil", - "field": "access_path", - "required": false - }, - { - "default": "nil", - "field": "route_prefix", - "required": false - }, - { - "default": "nil", - "field": "route_access_path", - "required": false - }, - { - "default": "nil", - "field": "schema_table", - "required": false - }, - { - "default": "nil", - "field": "schema_key", - "required": false - }, - { - "default": "nil", - "field": "schema_type", - "required": false - }, - { - "default": "nil", - "field": "schema_migration_type", - "required": false - }, - { - "default": "nil", - "field": "test_data_fixture", - "required": false - }, - { - "default": "nil", - "field": "test_setup_helper", - "required": false - } - ] - }, - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": { - "fields": [ - { - "default": "nil", - "field": "name", - "required": false - }, - { - "default": "nil", - "field": "module", - "required": false - }, - { - "default": "nil", - "field": "mix_dependency", - "required": false - }, - { - "default": "nil", - "field": "test_config", - "required": false - } - ] - }, - "Mix.Tasks.Phx.Gen.Auth.Migration": { - "fields": [ - { - "default": "nil", - "field": "ecto_adapter", - "required": false - }, - { - "default": "nil", - "field": "extensions", - "required": false - }, - { - "default": "nil", - "field": "column_definitions", - "required": false - } - ] - }, - "Phoenix.ActionClauseError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "nil", - "field": "args", - "required": false - }, - { - "default": "nil", - "field": "arity", - "required": false - }, - { - "default": "nil", - "field": "function", - "required": false - }, - { - "default": "nil", - "field": "module", - "required": false - }, - { - "default": "nil", - "field": "clauses", - "required": false - }, - { - "default": "nil", - "field": "kind", - "required": false - } - ] - }, - "Phoenix.MissingParamError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "nil", - "field": "message", - "required": false - }, - { - "default": "400", - "field": "plug_status", - "required": false - } - ] - }, - "Phoenix.NotAcceptableError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "nil", - "field": "message", - "required": false - }, - { - "default": "[]", - "field": "accepts", - "required": false - }, - { - "default": "406", - "field": "plug_status", - "required": false - } - ] - }, - "Phoenix.Router.MalformedURIError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "nil", - "field": "message", - "required": false - }, - { - "default": "400", - "field": "plug_status", - "required": false - } - ] - }, - "Phoenix.Router.NoRouteError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "404", - "field": "plug_status", - "required": false - }, - { - "default": "\"no route found\"", - "field": "message", - "required": false - }, - { - "default": "nil", - "field": "conn", - "required": false - }, - { - "default": "nil", - "field": "router", - "required": false - } - ] - }, - "Phoenix.Router.Resource": { - "fields": [ - { - "default": "nil", - "field": "path", - "required": false - }, - { - "default": "nil", - "field": "actions", - "required": false - }, - { - "default": "nil", - "field": "param", - "required": false - }, - { - "default": "nil", - "field": "route", - "required": false - }, - { - "default": "nil", - "field": "controller", - "required": false - }, - { - "default": "nil", - "field": "member", - "required": false - }, - { - "default": "nil", - "field": "collection", - "required": false - }, - { - "default": "nil", - "field": "singleton", - "required": false - } - ] - }, - "Phoenix.Router.Route": { - "fields": [ - { - "default": "nil", - "field": "verb", - "required": false - }, - { - "default": "nil", - "field": "line", - "required": false - }, - { - "default": "nil", - "field": "kind", - "required": false - }, - { - "default": "nil", - "field": "path", - "required": false - }, - { - "default": "nil", - "field": "hosts", - "required": false - }, - { - "default": "nil", - "field": "plug", - "required": false - }, - { - "default": "nil", - "field": "plug_opts", - "required": false - }, - { - "default": "nil", - "field": "helper", - "required": false - }, - { - "default": "nil", - "field": "private", - "required": false - }, - { - "default": "nil", - "field": "pipe_through", - "required": false - }, - { - "default": "nil", - "field": "assigns", - "required": false - }, - { - "default": "nil", - "field": "metadata", - "required": false - }, - { - "default": "nil", - "field": "trailing_slash?", - "required": false - }, - { - "default": "nil", - "field": "warn_on_verify?", - "required": false - } - ] - }, - "Phoenix.Router.Scope": { - "fields": [ - { - "default": "[]", - "field": "path", - "required": false - }, - { - "default": "[]", - "field": "alias", - "required": false - }, - { - "default": "[]", - "field": "as", - "required": false - }, - { - "default": "[]", - "field": "pipes", - "required": false - }, - { - "default": "[]", - "field": "hosts", - "required": false - }, - { - "default": "%{}", - "field": "private", - "required": false - }, - { - "default": "%{}", - "field": "assigns", - "required": false - }, - { - "default": ":debug", - "field": "log", - "required": false - }, - { - "default": "false", - "field": "trailing_slash?", - "required": false - } - ] - }, - "Phoenix.Socket": { - "fields": [ - { - "default": "%{}", - "field": "assigns", - "required": false - }, - { - "default": "nil", - "field": "channel", - "required": false - }, - { - "default": "nil", - "field": "channel_pid", - "required": false - }, - { - "default": "nil", - "field": "endpoint", - "required": false - }, - { - "default": "nil", - "field": "handler", - "required": false - }, - { - "default": "nil", - "field": "id", - "required": false - }, - { - "default": "false", - "field": "joined", - "required": false - }, - { - "default": "nil", - "field": "join_ref", - "required": false - }, - { - "default": "%{}", - "field": "private", - "required": false - }, - { - "default": "nil", - "field": "pubsub_server", - "required": false - }, - { - "default": "nil", - "field": "ref", - "required": false - }, - { - "default": "nil", - "field": "serializer", - "required": false - }, - { - "default": "nil", - "field": "topic", - "required": false - }, - { - "default": "nil", - "field": "transport", - "required": false - }, - { - "default": "nil", - "field": "transport_pid", - "required": false - } - ] - }, - "Phoenix.Socket.Broadcast": { - "fields": [ - { - "default": "nil", - "field": "topic", - "required": false - }, - { - "default": "nil", - "field": "event", - "required": false - }, - { - "default": "nil", - "field": "payload", - "required": false - } - ] - }, - "Phoenix.Socket.InvalidMessageError": { - "fields": [ - { - "default": "true", - "field": "__exception__", - "required": false - }, - { - "default": "nil", - "field": "message", - "required": false - } - ] - }, - "Phoenix.Socket.Message": { - "fields": [ - { - "default": "nil", - "field": "topic", - "required": false - }, - { - "default": "nil", - "field": "event", - "required": false - }, - { - "default": "nil", - "field": "payload", - "required": false - }, - { - "default": "nil", - "field": "ref", - "required": false - }, - { - "default": "nil", - "field": "join_ref", - "required": false - } - ] - }, - "Phoenix.Socket.Reply": { - "fields": [ - { - "default": "nil", - "field": "topic", - "required": false - }, - { - "default": "nil", - "field": "status", - "required": false - }, - { - "default": "nil", - "field": "payload", - "required": false - }, - { - "default": "nil", - "field": "ref", - "required": false - }, - { - "default": "nil", - "field": "join_ref", - "required": false - } - ] - }, - "Phoenix.VerifiedRoutes": { - "fields": [ - { - "default": "nil", - "field": "router", - "required": false - }, - { - "default": "nil", - "field": "route", - "required": false - }, - { - "default": "nil", - "field": "inspected_route", - "required": false - }, - { - "default": "nil", - "field": "warn_location", - "required": false - }, - { - "default": "nil", - "field": "test_path", - "required": false - } - ] - } - }, - "environment": "dev", - "project_path": "/Users/camonz/Code/phoenix", - "calls": [ - { - "caller": { - "function": "run/1", - "line": 61, - "module": "Mix.Tasks.Phx.Digest.Clean", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "output_path", - "arity": 1, - "function": "clean_all", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "run/1", - "line": 62, - "module": "Mix.Tasks.Phx.Digest.Clean", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "output_path, age, keep", - "arity": 3, - "function": "clean", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "run/1", - "line": 73, - "module": "Mix.Tasks.Phx.Digest", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "input_path, output_path, with_vsn?", - "arity": 3, - "function": "compile", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "run/1", - "line": 27, - "module": "Mix.Tasks.Phx", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "general", - "module": "Mix.Tasks.Phx" - } - }, - { - "caller": { - "function": "run/1", - "line": 20, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[\"Presence\"]", - "arity": 1, - "function": "run", - "module": "Mix.Tasks.Phx.Gen.Presence" - } - }, - { - "caller": { - "function": "run/1", - "line": 49, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Presence" - } - }, - { - "caller": { - "function": "run/1", - "line": 49, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.presence\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 42, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "context_base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 33, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "alias_name", - "arity": 1, - "function": "inflect", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 32, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 31, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 30, - "module": "Mix.Tasks.Phx.Gen.Presence", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run_args/0", - "line": 53, - "module": "Mix.Tasks.Phx.Server", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "iex_running?", - "module": "Mix.Tasks.Phx.Server" - } - }, - { - "caller": { - "function": "run/1", - "line": 36, - "module": "Mix.Tasks.Phx.Server", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "open_args", - "module": "Mix.Tasks.Phx.Server" - } - }, - { - "caller": { - "function": "run/1", - "line": 36, - "module": "Mix.Tasks.Phx.Server", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "run_args", - "module": "Mix.Tasks.Phx.Server" - } - }, - { - "caller": { - "function": "process_message/1", - "line": 46, - "module": "Inspect.Phoenix.Socket.Message", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "payload", - "arity": 1, - "function": "filter_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "inspect/2", - "line": 41, - "module": "Inspect.Phoenix.Socket.Message", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg", - "arity": 1, - "function": "process_message", - "module": "Inspect.Phoenix.Socket.Message" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 108, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Channel" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":erlang.hd(args)", - "arity": 1, - "function": "valid_name?", - "module": "Mix.Tasks.Phx.Gen.Channel" - } - }, - { - "caller": { - "function": "run/1", - "line": 80, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "String.split(<<\"User --from-channel \"::binary, String.Chars.to_string(channel_name)::binary>>)", - "arity": 1, - "function": "run", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "run/1", - "line": 64, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app, \"channels/user_socket.ex\"", - "arity": 2, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 55, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Channel" - } - }, - { - "caller": { - "function": "run/1", - "line": 54, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.channel\", binding, :erlang.++(\n [\n {:eex, \"channel.ex\",\n Path.join(\n web_prefix,\n <<\"channels/\"::binary, String.Chars.to_string(binding[:path])::binary,\n \"_channel.ex\"::binary>>\n )},\n {:eex, \"channel_test.exs\", test_path}\n ],\n maybe_case\n)", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 42, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "<>", - "arity": 1, - "function": "check_module_name_availability!", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 39, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "channel_name", - "arity": 1, - "function": "inflect", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 38, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 37, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 36, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 35, - "module": "Mix.Tasks.Phx.Gen.Channel", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Channel" - } - }, - { - "caller": { - "function": "build/1", - "line": 14, - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :bcrypt,\n module: Bcrypt,\n mix_dependency: \"{:bcrypt_elixir, \\\"~> 3.0\\\"}\",\n test_config: \"config :bcrypt_elixir, :log_rounds, 1\\n\"\n}", - "arity": 2, - "function": "%", - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" - } - }, - { - "caller": { - "function": "build/1", - "line": 27, - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :pbkdf2,\n module: Pbkdf2,\n mix_dependency: \"{:pbkdf2_elixir, \\\"~> 2.0\\\"}\",\n test_config: \"config :pbkdf2_elixir, :rounds, 1\\n\"\n}", - "arity": 2, - "function": "%", - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" - } - }, - { - "caller": { - "function": "build/1", - "line": 40, - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary, %{\n name: :argon2,\n module: Argon2,\n mix_dependency: \"{:argon2_elixir, \\\"~> 4.0\\\"}\",\n test_config: \"config :argon2_elixir, t_cost: 1, m_cost: 8\\n\"\n}", - "arity": 2, - "function": "%", - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" - } - }, - { - "caller": { - "function": "run/1", - "line": 16, - "module": "Mix.Tasks.Phx.Gen.Secret", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[\"64\"]", - "arity": 1, - "function": "run", - "module": "Mix.Tasks.Phx.Gen.Secret" - } - }, - { - "caller": { - "function": "run/1", - "line": 17, - "module": "Mix.Tasks.Phx.Gen.Secret", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "int", - "arity": 1, - "function": "parse!", - "module": "Mix.Tasks.Phx.Gen.Secret" - } - }, - { - "caller": { - "function": "run/1", - "line": 17, - "module": "Mix.Tasks.Phx.Gen.Secret", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parse!(int)", - "arity": 1, - "function": "random_string", - "module": "Mix.Tasks.Phx.Gen.Secret" - } - }, - { - "caller": { - "function": "run/1", - "line": 18, - "module": "Mix.Tasks.Phx.Gen.Secret", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "invalid_args!", - "module": "Mix.Tasks.Phx.Gen.Secret" - } - }, - { - "caller": { - "function": "parse!/1", - "line": 23, - "module": "Mix.Tasks.Phx.Gen.Secret", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "invalid_args!", - "module": "Mix.Tasks.Phx.Gen.Secret" - } - }, - { - "caller": { - "function": "touch/0", - "line": 29, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "touch_if_exists", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "touch/0", - "line": 26, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "modules", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "touch/0", - "line": 27, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.modules()", - "arity": 1, - "function": "modules_for_recompilation", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "touch/0", - "line": 28, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "modules_for_recompilation(Mix.Phoenix.modules())", - "arity": 1, - "function": "modules_to_file_paths", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 18, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "touch", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "modules_for_recompilation/1", - "line": 40, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "mod", - "arity": 1, - "function": "mix_recompile?", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "modules_for_recompilation/1", - "line": 40, - "module": "Mix.Tasks.Compile.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "mod", - "arity": 1, - "function": "phoenix_recompile?", - "module": "Mix.Tasks.Compile.Phoenix" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 93, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 92, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "pre_existing_channel", - "arity": 1, - "function": "valid_name?", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 92, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "name", - "arity": 1, - "function": "valid_name?", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 101, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 100, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "name", - "arity": 1, - "function": "valid_name?", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "run/1", - "line": 68, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app, \"endpoint.ex\"", - "arity": 2, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 61, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "run/1", - "line": 61, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.socket\", binding, [\n {:eex, \"socket.ex\",\n Path.join(\n web_prefix,\n <<\"channels/\"::binary, String.Chars.to_string(binding[:path])::binary, \"_socket.ex\"::binary>>\n )},\n {:eex, \"socket.js\",\n <<\"assets/js/\"::binary, String.Chars.to_string(binding[:path])::binary, \"_socket.js\"::binary>>}\n]", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 59, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "<>", - "arity": 1, - "function": "check_module_name_availability!", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 43, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pre_existing_channel", - "arity": 1, - "function": "inflect", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 39, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "socket_name", - "arity": 1, - "function": "inflect", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 38, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 37, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 35, - "module": "Mix.Tasks.Phx.Gen.Socket", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Socket" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 72, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "<<\"Expected the schema argument, \"::binary, Kernel.inspect(schema)::binary,\n \", to be a valid module name\"::binary>>", - "arity": 1, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 69, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema", - "arity": 1, - "function": "valid?", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 76, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "\"Invalid arguments\"", - "arity": 1, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "run/1", - "line": 50, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema, paths, [schema: schema]", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "run/1", - "line": 48, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "run/1", - "line": 46, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 44, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 95, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 96, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "files_to_be_generated(schema)", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.embedded\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 106, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "build/1", - "line": 62, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema_name, nil, attrs, opts", - "arity": 4, - "function": "new", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "build/1", - "line": 56, - "module": "Mix.Tasks.Phx.Gen.Embedded", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parsed", - "arity": 1, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Embedded" - } - }, - { - "caller": { - "function": "run/1", - "line": 170, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "run/1", - "line": 171, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, paths, binding)", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "run/1", - "line": 167, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "run/1", - "line": 165, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 160, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "\"scope\", schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 159, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn_scope, schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 140, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_code_injection", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 129, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "args, [name_optional: true]", - "arity": 2, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 177, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "context_files", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 176, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 178, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": ":erlang.++(files_to_be_generated(context), context_files(context))", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 251, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 228, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 239, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 193, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 192, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 211, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 210, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.json\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 209, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Json" - } - }, - { - "caller": { - "function": "context_files/1", - "line": 182, - "module": "Mix.Tasks.Phx.Gen.Json", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 164, - "module": "Phoenix.ChannelTest.NoopSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{join_ref: nil, ref: nil, topic: msg.topic(), event: msg.event(), payload: msg.payload()}", - "arity": 2, - "function": "%", - "module": "Phoenix.ChannelTest.NoopSerializer" - } - }, - { - "caller": { - "function": "column_definitions/1", - "line": 23, - "module": "Mix.Tasks.Phx.Gen.Auth.Migration", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "field, ecto_adapter", - "arity": 2, - "function": "column_definition", - "module": "Mix.Tasks.Phx.Gen.Auth.Migration" - } - }, - { - "caller": { - "function": "build/1", - "line": 10, - "module": "Mix.Tasks.Phx.Gen.Auth.Migration", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ecto_adapter", - "arity": 1, - "function": "column_definitions", - "module": "Mix.Tasks.Phx.Gen.Auth.Migration" - } - }, - { - "caller": { - "function": "build/1", - "line": 9, - "module": "Mix.Tasks.Phx.Gen.Auth.Migration", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ecto_adapter", - "arity": 1, - "function": "extensions", - "module": "Mix.Tasks.Phx.Gen.Auth.Migration" - } - }, - { - "caller": { - "function": "build/1", - "line": 7, - "module": "Mix.Tasks.Phx.Gen.Auth.Migration", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Auth.Migration, %{\n ecto_adapter: ecto_adapter,\n extensions: extensions(ecto_adapter),\n column_definitions: column_definitions(ecto_adapter)\n}", - "arity": 2, - "function": "%", - "module": "Mix.Tasks.Phx.Gen.Auth.Migration" - } - }, - { - "caller": { - "function": "scopes_from_config/1", - "line": 47, - "module": "Mix.Phoenix.Scope", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "name, opts", - "arity": 2, - "function": "new!", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "scope_from_opts/3", - "line": 81, - "module": "Mix.Phoenix.Scope", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app", - "arity": 1, - "function": "default_scope", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "scope_from_opts/3", - "line": 85, - "module": "Mix.Phoenix.Scope", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app", - "arity": 1, - "function": "scopes_from_config", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "default_scope/1", - "line": 54, - "module": "Mix.Phoenix.Scope", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app", - "arity": 1, - "function": "scopes_from_config", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "web_module/0", - "line": 94, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "web_module/0", - "line": 94, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "web_module/0", - "line": 92, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/3", - "line": 51, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "web_module", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "new/3", - "line": 45, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.Context, %{\n name: context_name,\n module: module,\n schema: schema,\n alias: alias,\n base_module: base,\n web_module: web_module(),\n basename: basename,\n file: file,\n test_file: test_file,\n test_fixtures_file: test_fixtures_file,\n dir: dir,\n generate?: generate?,\n context_app: ctx_app,\n opts: opts,\n scope: schema.scope()\n}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "new/3", - "line": 41, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, \"test/support/fixtures\"", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/3", - "line": 39, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, basedir", - "arity": 2, - "function": "context_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/3", - "line": 37, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, basedir", - "arity": 2, - "function": "context_lib_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/3", - "line": 35, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_name", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/3", - "line": 32, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "context_base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/3", - "line": 31, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/2", - "line": 27, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.Schema, %{\n alias: nil,\n api_route_prefix: nil,\n assocs: [],\n attrs: [],\n binary_id: false,\n collection: nil,\n context_app: nil,\n defaults: [],\n embedded?: false,\n file: nil,\n fixture_params: [],\n fixture_unique_functions: [],\n generate?: true,\n human_plural: nil,\n human_singular: nil,\n indexes: [],\n migration?: false,\n migration_defaults: nil,\n migration_module: nil,\n module: nil,\n optionals: [],\n opts: [],\n params: %{},\n plural: nil,\n prefix: nil,\n redacts: [],\n repo: nil,\n repo_alias: nil,\n route_helper: nil,\n route_prefix: nil,\n sample_id: nil,\n scope: nil,\n singular: nil,\n string_attr: nil,\n table: nil,\n timestamp_type: :naive_datetime,\n types: [],\n uniques: [],\n web_namespace: nil,\n web_path: nil\n}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "new/2", - "line": 27, - "module": "Mix.Phoenix.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context_name, %Mix.Phoenix.Schema{\n alias: nil,\n api_route_prefix: nil,\n assocs: [],\n attrs: [],\n binary_id: false,\n collection: nil,\n context_app: nil,\n defaults: [],\n embedded?: false,\n file: nil,\n fixture_params: [],\n fixture_unique_functions: [],\n generate?: true,\n human_plural: nil,\n human_singular: nil,\n indexes: [],\n migration?: false,\n migration_defaults: nil,\n migration_module: nil,\n module: nil,\n optionals: [],\n opts: [],\n params: %{},\n plural: nil,\n prefix: nil,\n redacts: [],\n repo: nil,\n repo_alias: nil,\n route_helper: nil,\n route_prefix: nil,\n sample_id: nil,\n scope: nil,\n singular: nil,\n string_attr: nil,\n table: nil,\n timestamp_type: :naive_datetime,\n types: [],\n uniques: [],\n web_namespace: nil,\n web_path: nil\n}, opts", - "arity": 3, - "function": "new", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "run/2", - "line": 87, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router_mod, endpoint_mod", - "arity": 2, - "function": "format", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "run/2", - "line": 83, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "url, {router_mod, opts}", - "arity": 2, - "function": "get_url_info", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "run/2", - "line": 78, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts[:endpoint], base", - "arity": 2, - "function": "endpoint", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "run/2", - "line": 78, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts[:router], base", - "arity": 2, - "function": "router", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "run/2", - "line": 77, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "passed_router, base", - "arity": 2, - "function": "router", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "run/1", - "line": 65, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "router/2", - "line": 142, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "old_router", - "arity": 1, - "function": "loaded", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "router/2", - "line": 142, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "web_router", - "arity": 1, - "function": "loaded", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "router/2", - "line": 140, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "base, \"Router\"", - "arity": 2, - "function": "app_mod", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "router/2", - "line": 139, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "base, \"Router\"", - "arity": 2, - "function": "web_mod", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "router/2", - "line": 158, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "arg_router", - "arity": 1, - "function": "loaded", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "get_url_info/2", - "line": 110, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, func_name", - "arity": 2, - "function": "get_line_number", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "get_url_info/2", - "line": 108, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_file_path", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "get_url_info/2", - "line": 96, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router_mod, method, path, \"\"", - "arity": 4, - "function": "route_info", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "endpoint/2", - "line": 118, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "base, \"Endpoint\"", - "arity": 2, - "function": "web_mod", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "endpoint/2", - "line": 118, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "web_mod(base, \"Endpoint\")", - "arity": 1, - "function": "loaded", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "endpoint/2", - "line": 122, - "module": "Mix.Tasks.Phx.Routes", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Module.concat([module])", - "arity": 1, - "function": "loaded", - "module": "Mix.Tasks.Phx.Routes" - } - }, - { - "caller": { - "function": "run/1", - "line": 173, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCPW\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFP\\0T\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x13\\x1DP\\x1DH\\x1DX\\x1D_\\x1DH\\x1DO\\x1DS\\x1DTx\\0\\x13\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"PHX_HOST\"\n}, <<\"[warn] Environment based URL export is missing from runtime configuration.\\n\\nAdd the following to your config/runtime.exs:\\n\\n host = System.get_env(\\\"PHX_HOST\\\") || \\\"example.com\\\"\\n\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(web_namespace)::binary,\n \".Endpoint,\\n ...,\\n url: [host: host, port: 443]\\n\"::binary>>", - "arity": 3, - "function": "post_install_instructions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 163, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCP[\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFP\\0R\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x17\\x1DP\\x1DH\\x1DX\\x1D_\\x1DS\\x1DE\\x1DR\\x1DV\\x1DE\\x1DRx\\0\\x17\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"PHX_SERVER\"\n}, <<\"[warn] Conditional server startup is missing from runtime configuration.\\n\\nAdd the following to the top of your config/runtime.exs:\\n\\n if System.get_env(\\\"PHX_SERVER\\\") do\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(web_namespace)::binary, \".Endpoint, server: true\\n end\\n\"::binary>>", - "arity": 3, - "function": "post_install_instructions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 150, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "\"config/runtime.exs\", %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 0, 0, 0,\n \"ERCPY\\0\\0\\0\\0\\0\\0\\0Q\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFFE\\06\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x15\\x1DE\\x1DC\\x1DT\\x1DO\\x1D_\\x1DI\\x1DP\\x1DV\\x1D6x\\0\\x15\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"ECTO_IPV6\"\n}, <<\"[warn] Conditional IPv6 support missing from runtime configuration.\\n\\nAdd the following to your config/runtime.exs:\\n\\n maybe_ipv6 = if System.get_env(\\\"ECTO_IPV6\\\") in ~w(true 1), do: [:inet6], else: []\\n\\n config :\"::binary,\n String.Chars.to_string(app)::binary, \", \"::binary,\n String.Chars.to_string(app_namespace)::binary,\n \".Repo,\\n ...,\\n socket_options: maybe_ipv6\\n\"::binary>>", - "arity": 3, - "function": "post_install_instructions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 139, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "app", - "arity": 1, - "function": "ecto_instructions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 131, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "docker_instructions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 115, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding, opts", - "arity": 2, - "function": "gen_docker", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 110, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "app, \"release.ex\"", - "arity": 2, - "function": "context_lib_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.release\", binding, [\n {:eex, \"rel/migrate.sh.eex\", \"rel/overlays/bin/migrate\"},\n {:eex, \"rel/migrate.bat.eex\", \"rel/overlays/bin/migrate.bat\"},\n {:eex, \"release.ex\", Mix.Phoenix.context_lib_path(app, \"release.ex\")}\n]", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 101, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "run/1", - "line": 101, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.release\", binding, [\n {:eex, \"rel/server.sh.eex\", \"rel/overlays/bin/server\"},\n {:eex, \"rel/server.bat.eex\", \"rel/overlays/bin/server.bat\"}\n]", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 93, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "app_namespace", - "arity": 1, - "function": "web_module", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 92, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 91, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 81, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "parse_args", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "parse_args/1", - "line": 193, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "socket_db_adaptor_installed?", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "parse_args/1", - "line": 192, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "ecto_sql_installed?", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "gen_docker/2", - "line": 297, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "paths", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "gen_docker/2", - "line": 297, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths(), \"priv/templates/phx.gen.release\", binding, [{:eex, \"Dockerfile.eex\", \"Dockerfile\"}, {:eex, \"dockerignore.eex\", \".dockerignore\"}]", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "gen_docker/2", - "line": 274, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "\"\", otp_vsn", - "arity": 2, - "function": "elixir_and_debian_vsn", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "gen_docker/2", - "line": 269, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "wanted_elixir_vsn, otp_vsn", - "arity": 2, - "function": "elixir_and_debian_vsn", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "gen_docker/2", - "line": 266, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_vsn", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "fetch_body!/1", - "line": 346, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "protocol_versions", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "fetch_body!/1", - "line": 323, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":ssl", - "arity": 1, - "function": "ensure_app!", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "fetch_body!/1", - "line": 322, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":inets", - "arity": 1, - "function": "ensure_app!", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "elixir_and_debian_vsn/2", - "line": 246, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url", - "arity": 1, - "function": "fetch_body!", - "module": "Mix.Tasks.Phx.Gen.Release" - } - }, - { - "caller": { - "function": "elixir_and_debian_vsn/2", - "line": 247, - "module": "Mix.Tasks.Phx.Gen.Release", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "do_call/4", - "line": 29, - "module": "Phoenix.Endpoint.SyncCodeReloadPlug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, endpoint, opts, false", - "arity": 4, - "function": "do_call", - "module": "Phoenix.Endpoint.SyncCodeReloadPlug" - } - }, - { - "caller": { - "function": "do_call/4", - "line": 28, - "module": "Phoenix.Endpoint.SyncCodeReloadPlug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "sync", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "do_call/4", - "line": 26, - "module": "Phoenix.Endpoint.SyncCodeReloadPlug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "UndefinedFunctionError, %{module: ^endpoint}", - "arity": 2, - "function": "%", - "module": "Phoenix.Endpoint.SyncCodeReloadPlug" - } - }, - { - "caller": { - "function": "call/2", - "line": 18, - "module": "Phoenix.Endpoint.SyncCodeReloadPlug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, endpoint, opts, true", - "arity": 4, - "function": "do_call", - "module": "Phoenix.Endpoint.SyncCodeReloadPlug" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 117, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture", - "arity": 1, - "function": "valid_message?", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 112, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 107, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 102, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "notifier", - "arity": 1, - "function": "valid_notifier?", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 97, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "valid?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 62, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, binding, paths", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "run/1", - "line": 63, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, binding, paths)", - "arity": 1, - "function": "maybe_print_mailer_installation_instructions", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "run/1", - "line": 55, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "run/1", - "line": 53, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 45, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "notifier_module", - "arity": 1, - "function": "inflect", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 43, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 176, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 177, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "files_to_be_generated(context)", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "parse_opts/1", - "line": 84, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Keyword.merge([context: true], opts), opts[:context_app]", - "arity": 2, - "function": "put_context_app", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 162, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.notifier\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 160, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "build/2", - "line": 73, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "notifier_module, opts", - "arity": 2, - "function": "new", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "build/2", - "line": 70, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parsed, help", - "arity": 2, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "build/2", - "line": 68, - "module": "Mix.Tasks.Phx.Gen.Notifier", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "parse_opts", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "scope_assign_route_prefix/1", - "line": 332, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "<<\"@\"::binary, String.Chars.to_string(assign_key)::binary>>, schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 171, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "run/1", - "line": 172, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, paths, binding)", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "run/1", - "line": 168, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "run/1", - "line": 166, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 161, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "scope_assign_route_prefix", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "run/1", - "line": 160, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "\"scope\", schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 159, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn_scope, schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 156, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "inputs", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "run/1", - "line": 141, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_code_injection", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 130, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "args, [name_optional: true]", - "arity": 2, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 128, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Html", - "arity": 1, - "function": "ensure_live_view_compat!", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 178, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "context_files", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 177, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 179, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": ":erlang.++(files_to_be_generated(context), context_files(context))", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 256, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 233, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 244, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "label/1", - "line": 326, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "String.Chars.to_string(key)", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 314, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 307, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 298, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "type", - "arity": 1, - "function": "default_options", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 297, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 289, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 286, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 283, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 280, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 277, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 274, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 271, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 268, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 265, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 194, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 193, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 217, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 216, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.html\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 215, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Html" - } - }, - { - "caller": { - "function": "context_files/1", - "line": 183, - "module": "Mix.Tasks.Phx.Gen.Html", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "socket_process_dict/1", - "line": 55, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "dictionary, :\"$process_label\"", - "arity": 2, - "function": "keyfind", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "socket_process_dict/1", - "line": 54, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "info, :dictionary", - "arity": 2, - "function": "keyfind", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "socket_process?/1", - "line": 78, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "pid", - "arity": 1, - "function": "socket_process_dict", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "socket/1", - "line": 161, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "channel_pid", - "arity": 1, - "function": "socket", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "socket/1", - "line": 160, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "channel_pid", - "arity": 1, - "function": "channel_process?", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "list_sockets/0", - "line": 39, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "dict, :\"$process_label\"", - "arity": 2, - "function": "keyfind", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "list_sockets/0", - "line": 38, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "pid", - "arity": 1, - "function": "socket_process_dict", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "list_channels/1", - "line": 128, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket_pid", - "arity": 1, - "function": "socket_process?", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "channel_process?/1", - "line": 90, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "dictionary, :\"$process_label\"", - "arity": 2, - "function": "keyfind", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "channel_process?/1", - "line": 89, - "module": "Phoenix.Debug", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "info, :dictionary", - "arity": 2, - "function": "keyfind", - "module": "Phoenix.Debug" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 265, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "plural", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "validate_args!/2", - "line": 263, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema", - "arity": 1, - "function": "valid?", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 291, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "ss", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 291, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "mm", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 291, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "hh", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 291, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "d", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 291, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "m", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "run/1", - "line": 177, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "run/1", - "line": 178, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(schema, paths, binding)", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "run/1", - "line": 168, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "run/1", - "line": 166, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 165, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args, []", - "arity": 2, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 183, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 184, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "files_to_be_generated(schema)", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 240, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.schema\", binding, [{:eex, \"migration.exs\", migration_path}]", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 238, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "timestamp", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 235, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, \"priv/repo/migrations/\"", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 232, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, <<\"priv/\"::binary, String.Chars.to_string(repo_name)::binary, \"/migrations/\"::binary>>", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 222, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.schema\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 221, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "build/3", - "line": 198, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema_name, plural, attrs, opts", - "arity": 4, - "function": "new", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "build/3", - "line": 195, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Keyword.merge(parent_opts, schema_opts), schema_opts[:context_app]", - "arity": 2, - "function": "put_context_app", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "build/3", - "line": 196, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "put_context_app(Keyword.merge(parent_opts, schema_opts), schema_opts[:context_app])", - "arity": 1, - "function": "maybe_update_repo_module", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "build/3", - "line": 190, - "module": "Mix.Tasks.Phx.Gen.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parsed, help", - "arity": 2, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "reply/2", - "line": 675, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket_ref, {status, %{}}", - "arity": 2, - "function": "reply", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "reply/2", - "line": 679, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "transport_pid, join_ref, ref, topic, {status, payload}, serializer", - "arity": 6, - "function": "reply", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "push/3", - "line": 630, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "transport_pid, socket.join_ref(), topic, event, message, socket.serializer()", - "arity": 6, - "function": "push", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "push/3", - "line": 629, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "assert_joined!", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "broadcast_from!/3", - "line": 602, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, channel_pid, topic, event, message", - "arity": 5, - "function": "broadcast_from!", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from!/3", - "line": 600, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "assert_joined!", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "broadcast_from/3", - "line": 592, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, channel_pid, topic, event, message", - "arity": 5, - "function": "broadcast_from", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from/3", - "line": 590, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "assert_joined!", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "broadcast!/3", - "line": 569, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, topic, event, message", - "arity": 4, - "function": "broadcast!", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast!/3", - "line": 568, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "assert_joined!", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "broadcast/3", - "line": 561, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, topic, event, message", - "arity": 4, - "function": "broadcast", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast/3", - "line": 560, - "module": "Phoenix.Channel", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "assert_joined!", - "module": "Phoenix.Channel" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 36, - "module": "Phoenix.CodeReloader.MixListener", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "modules", - "arity": 1, - "function": "purge_modules", - "module": "Phoenix.CodeReloader.MixListener" - } - }, - { - "caller": { - "function": "watch/2", - "line": 42, - "module": "Phoenix.Endpoint.Watcher", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "cd", - "module": "Phoenix.Endpoint.Watcher" - } - }, - { - "caller": { - "function": "exception/1", - "line": 37, - "module": "Phoenix.MissingParamError", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.MissingParamError, %{__exception__: true, plug_status: 400, message: msg}", - "arity": 2, - "function": "%", - "module": "Phoenix.MissingParamError" - } - }, - { - "caller": { - "function": "start_link/3", - "line": 111, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "scheme, endpoint, ref", - "arity": 3, - "function": "info", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "start_link/3", - "line": 107, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "scheme, endpoint, ref", - "arity": 3, - "function": "info", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "start_link/3", - "line": 103, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "scheme, endpoint, ref", - "arity": 3, - "function": "info", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "server_info/2", - "line": 144, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, scheme", - "arity": 2, - "function": "make_ref", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "port_to_integer/1", - "line": 137, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "System.get_env(env_var)", - "arity": 1, - "function": "port_to_integer", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "info/3", - "line": 121, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "scheme, ref", - "arity": 2, - "function": "bound_address", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "child_specs/2", - "line": 66, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "scheme, endpoint, opts, config[:code_reloader]", - "arity": 4, - "function": "child_spec", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "child_specs/2", - "line": 65, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "port", - "arity": 1, - "function": "port_to_integer", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "child_spec/4", - "line": 83, - "module": "Phoenix.Endpoint.Cowboy2Adapter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, scheme", - "arity": 2, - "function": "make_ref", - "module": "Phoenix.Endpoint.Cowboy2Adapter" - } - }, - { - "caller": { - "function": "exception/1", - "line": 15, - "module": "Phoenix.NotAcceptableError", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[message: msg]", - "arity": 1, - "function": "exception", - "module": "Phoenix.NotAcceptableError" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 45, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "from, reply, :erlang.apply(m, f, as), output", - "arity": 4, - "function": "put_chars", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 42, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "from, reply, chars, output", - "arity": 4, - "function": "put_chars", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 39, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "from, reply, :erlang.apply(m, f, as), output", - "arity": 4, - "function": "put_chars", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 36, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "from, reply, chars, output", - "arity": 4, - "function": "put_chars", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "handle_cast/2", - "line": 26, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "diagnostic_to_chars", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "diagnostic_to_chars/1", - "line": 66, - "module": "Phoenix.CodeReloader.Proxy", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "position", - "arity": 1, - "function": "position", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "validate_context!/1", - "line": 189, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "\"cannot use form as the schema name because it conflicts with the LiveView assigns!\"", - "arity": 1, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "scope_param_prefix/1", - "line": 441, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "scope_param", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "scope_assign_route_prefix/1", - "line": 449, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "<<\"@\"::binary, String.Chars.to_string(assign_key)::binary>>, schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 181, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, binding, paths", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 182, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, binding, paths)", - "arity": 1, - "function": "maybe_inject_imports", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 183, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_imports(copy_new_files(context, binding, paths))", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 178, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 176, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 171, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "scope_assign_route_prefix", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 170, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "socket_scope, schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 169, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "scope_param_prefix", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 168, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "scope_param", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 167, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "\"scope\", schema", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/1", - "line": 162, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "inputs", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 146, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_code_injection", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 135, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "validate_context!", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "run/1", - "line": 134, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "args, [name_optional: true]", - "arity": 2, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 132, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Live", - "arity": 1, - "function": "ensure_live_view_compat!", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 201, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "context_files", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 200, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 202, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": ":erlang.++(files_to_be_generated(context), context_files(context))", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 330, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "maybe_print_upgrade_info", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 329, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 311, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "live_route_instructions", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 319, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "live_route_instructions", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 317, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 300, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "maybe_inject_imports/1", - "line": 262, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, file, file_path, inject", - "arity": 4, - "function": "do_inject_imports", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "maybe_inject_imports/1", - "line": 253, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "label/1", - "line": 431, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "String.Chars.to_string(key)", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 419, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 412, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 403, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "type", - "arity": 1, - "function": "default_options", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 402, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 394, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 391, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 388, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 385, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 382, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 379, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 376, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 373, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "inputs/1", - "line": 370, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "label", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 215, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 214, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 247, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 246, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.live\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 232, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Live" - } - }, - { - "caller": { - "function": "context_files/1", - "line": 206, - "module": "Mix.Tasks.Phx.Gen.Live", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "template/1", - "line": 323, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "output", - "arity": 1, - "function": "format_output", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "sync/0", - "line": 71, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "sync", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "reload!/2", - "line": 63, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "endpoint, opts", - "arity": 2, - "function": "reload!", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "reload/2", - "line": 56, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, opts", - "arity": 2, - "function": "reload!", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "init/1", - "line": 106, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 2, - "function": "reload", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "format_output/1", - "line": 333, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "String.trim(output)", - "arity": 1, - "function": "remove_ansi_escapes", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "child_spec/1", - "line": 75, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "opts", - "arity": 1, - "function": "child_spec", - "module": "Phoenix.CodeReloader.MixListener" - } - }, - { - "caller": { - "function": "call/2", - "line": 120, - "module": "Phoenix.CodeReloader", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "output", - "arity": 1, - "function": "template", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "init/1", - "line": 444, - "module": "Phoenix.Presence.Tracker", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "state", - "arity": 1, - "function": "init", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 449, - "module": "Phoenix.Presence.Tracker", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "msg, state", - "arity": 2, - "function": "handle_info", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_diff/2", - "line": 446, - "module": "Phoenix.Presence.Tracker", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "diff, state", - "arity": 2, - "function": "handle_diff", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "update/3", - "line": 164, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "clear_cache", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "merger/3", - "line": 111, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 3, - "function": "merger", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "merge/2", - "line": 107, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 3, - "function": "merger", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "init/1", - "line": 134, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, config, []", - "arity": 3, - "function": "update", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 154, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "clear_cache", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 147, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, changed, permanent", - "arity": 3, - "function": "update", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "from_env/3", - "line": 92, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "defaults, config", - "arity": 2, - "function": "merge", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "from_env/3", - "line": 90, - "module": "Phoenix.Config", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, module", - "arity": 2, - "function": "fetch_config", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "to_param/1", - "line": 127, - "module": "Phoenix.Param.Any", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "id", - "arity": 1, - "function": "to_param", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "exception/1", - "line": 25, - "module": "Phoenix.Router.MalformedURIError", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[message: msg]", - "arity": 1, - "function": "exception", - "module": "Phoenix.Router.MalformedURIError" - } - }, - { - "caller": { - "function": "exception/1", - "line": 13, - "module": "Phoenix.Router.NoRouteError", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Router.NoRouteError, %{\n __exception__: true,\n plug_status: 404,\n message:\n <<\"no route found for \"::binary, String.Chars.to_string(conn.method())::binary, \" \"::binary,\n String.Chars.to_string(path)::binary, \" (\"::binary, Kernel.inspect(router)::binary,\n \")\"::binary>>,\n conn: conn,\n router: router\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router.NoRouteError" - } - }, - { - "caller": { - "function": "test_config_inject/2", - "line": 71, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "file, code_to_inject", - "arity": 2, - "function": "config_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "test_config_inject/2", - "line": 68, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "hashing_library", - "arity": 1, - "function": "test_config_code", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "test_config_inject/2", - "line": 69, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "test_config_code(hashing_library), file", - "arity": 2, - "function": "normalize_line_endings_to_file", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "test_config_help_text/2", - "line": 82, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "hashing_library", - "arity": 1, - "function": "test_config_code", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "test_config_help_text/2", - "line": 82, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "test_config_code(hashing_library), 4", - "arity": 2, - "function": "indent_spaces", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "router_plug_inject/2", - "line": 103, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "router_plug_code", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "router_plug_inject/2", - "line": 101, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "file, router_plug_code(binding), fn capture, capture ->\n Regex.replace(\n Regex.compile!(\n <<\"^(\\\\s*)\"::binary, \"plug :put_secure_browser_headers\"::binary,\n \".*(\\\\r\\\\n|\\\\n|$)\"::binary>>,\n \"Um\"\n ),\n capture,\n <<\"\\\\0\\\\1\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", - "arity": 3, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "router_plug_help_text/2", - "line": 128, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "router_plug_code", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "router_plug_help_text/2", - "line": 123, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "router_plug_name", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "router_plug_code/1", - "line": 134, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "router_plug_name", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "normalize_line_endings_to_file/2", - "line": 301, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file", - "arity": 1, - "function": "get_line_ending", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "mix_dependency_inject/2", - "line": 16, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mixfile, dependency", - "arity": 2, - "function": "do_mix_dependency_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "mix_dependency_inject/2", - "line": 15, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mixfile, dependency", - "arity": 2, - "function": "ensure_not_already_injected", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_unless_contains/4", - "line": 251, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "code, dup_check", - "arity": 2, - "function": "ensure_not_already_injected", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_unless_contains/3", - "line": 245, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "code, dup_check, dup_check, inject_fn", - "arity": 4, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "do_mix_dependency_inject/2", - "line": 29, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "mixfile, string_to_split_on", - "arity": 2, - "function": "split_with_self", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "config_inject/2", - "line": 45, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "file, code_to_inject, fn capture, capture ->\n Regex.replace(\n %{\n __struct__: Regex,\n opts: [],\n re_pattern:\n {:re_pattern, 2, 0, 0,\n \"ERCP\\x9D\\0\\0\\0\\0\\0\\0\\0A\\b\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\0\\0g\\0\\0\\0\\x02\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0Y\\x85\\0!\\0\\x01\\x1Du\\x1Ds\\x1De\\x1D \\x1DM\\x1Di\\x1Dx\\x1D.\\x1DC\\x1Do\\x1Dn\\x1Df\\x1Di\\x1Dgw\\0\\x1D\\x1Di\\x1Dm\\x1Dp\\x1Do\\x1Dr\\x1Dt\\x1D \\x1DC\\x1Do\\x1Dn\\x1Df\\x1Di\\x1Dgx\\0>\\x85\\0\\t\\0\\x02\\x1D\\r\\x1D\\nw\\0\\x05\\x1D\\nw\\0\\x04\\x19x\\0\\x12x\\0Y\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"(use Mix\\\\.Config|import Config)(\\\\r\\\\n|\\\\n|$)\"\n },\n capture,\n <<\"\\\\0\\\\2\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", - "arity": 3, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_at_end_of_nav_tag/2", - "line": 215, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, dup_check, code, fn capture, capture ->\n Regex.replace(\n %{\n __struct__: Regex,\n opts: [:multiline],\n re_pattern:\n {:re_pattern, 1, 0, 0,\n \"ERCP]\\0\\0\\0\\x02\\0\\0\\0A\\0\\0\\0\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\0\\0>\\0\\0\\0\\x01\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\x83\\0\\x19\\x85\\0\\a\\0\\x01^\\tx\\0\\a\\x1D<\\x1D/\\x1Dn\\x1Da\\x1Dv\\x1D>x\\0\\x19\\0\"},\n re_version: {\"8.45 2021-06-15\", :little},\n source: \"(\\\\s*)\"\n },\n capture,\n <>,\n global: false\n )\nend", - "arity": 4, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_at_end_of_nav_tag/2", - "line": 213, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding, padding, newline", - "arity": 3, - "function": "app_layout_menu_code_to_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_at_end_of_nav_tag/2", - "line": 212, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, \"\"", - "arity": 2, - "function": "formatting_info", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_after_opening_body_tag/2", - "line": 228, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, dup_check, code, fn capture, capture ->\n Regex.replace(\n Regex.compile!(\n <<\"^(\\\\s*)\"::binary, String.Chars.to_string(anchor_line)::binary,\n \".*(\\\\r\\\\n|\\\\n|$)\"::binary>>,\n \"Um\"\n ),\n capture,\n <<\"\\\\0\"::binary, String.Chars.to_string(capture)::binary, \"\\\\2\"::binary>>,\n global: false\n )\nend", - "arity": 4, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_after_opening_body_tag/2", - "line": 226, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding, padding, newline", - "arity": 3, - "function": "app_layout_menu_code_to_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject_after_opening_body_tag/2", - "line": 225, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, anchor_line", - "arity": 2, - "function": "formatting_info", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject/2", - "line": 148, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding, template_str", - "arity": 2, - "function": "app_layout_menu_inject_after_opening_body_tag", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_inject/2", - "line": 146, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding, template_str", - "arity": 2, - "function": "app_layout_menu_inject_at_end_of_nav_tag", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_help_text/2", - "line": 157, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "app_layout_menu_code_to_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "app_layout_menu_code_to_inject/3", - "line": 197, - "module": "Mix.Tasks.Phx.Gen.Auth.Injector", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "template, padding, newline", - "arity": 3, - "function": "indent_spaces", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "unsuffix/2", - "line": 0, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "prefix_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "resource_name/2", - "line": 24, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "List.last(Module.split(String.Chars.to_string(alias))), suffix", - "arity": 2, - "function": "unsuffix", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "resource_name/2", - "line": 25, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "unsuffix(List.last(Module.split(String.Chars.to_string(alias))), suffix)", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "humanize/1", - "line": 121, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":erlang.atom_to_binary(atom)", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "camelize/2", - "line": 99, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "t, :lower", - "arity": 2, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "camelize/2", - "line": 103, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "h", - "arity": 1, - "function": "to_lower_char", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "camelize/2", - "line": 102, - "module": "Phoenix.Naming", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "value", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "render/6", - "line": 124, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, template, assigns", - "arity": 3, - "function": "render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/6", - "line": 119, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/6", - "line": 113, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "maybe_fetch_query_params", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "render/6", - "line": 114, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "maybe_fetch_query_params(conn), opts", - "arity": 2, - "function": "fetch_view_format", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "render/6", - "line": 116, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Plug.Conn.put_status(fetch_view_format(maybe_fetch_query_params(conn), opts), status), case opts[:root_layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\nend", - "arity": 2, - "function": "put_root_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/6", - "line": 117, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Controller.put_root_layout(\n Plug.Conn.put_status(fetch_view_format(maybe_fetch_query_params(conn), opts), status),\n case opts[:root_layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\n end\n), case opts[:layout] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> false\n x -> x\nend", - "arity": 2, - "function": "put_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 187, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, fallback_format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 188, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Controller.put_format(conn, fallback_format), fallback_view", - "arity": 2, - "function": "put_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 174, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, fallback_format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 175, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Controller.put_format(conn, fallback_format), fallback_view", - "arity": 2, - "function": "put_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 170, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, view", - "arity": 2, - "function": "put_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 166, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_formats/2", - "line": 163, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, Enum.map(formats, fn capture -> :erlang.element(1, capture) end)", - "arity": 2, - "function": "accepts", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "maybe_fetch_query_params/1", - "line": 132, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.Unfetched, %{}", - "arity": 2, - "function": "%", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "instrument_render_and_send/5", - "line": 85, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, status, kind, reason, stack, opts", - "arity": 6, - "function": "render", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "instrument_render_and_send/5", - "line": 72, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, kind, reason", - "arity": 3, - "function": "error_conn", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "instrument_render_and_send/5", - "line": 71, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "kind, reason", - "arity": 2, - "function": "status", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "fetch_view_format/2", - "line": 148, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, Enum.map(accepts, fn capture -> {capture, view} end)", - "arity": 2, - "function": "put_formats", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "fetch_view_format/2", - "line": 145, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, Enum.map(formats, fn {k, v} -> {:erlang.atom_to_binary(k), v} end)", - "arity": 2, - "function": "put_formats", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "__debugger_banner__/5", - "line": 104, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router", - "arity": 1, - "function": "format", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "__catch__/5", - "line": 65, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "kind, reason, stack", - "arity": 3, - "function": "maybe_raise", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "__catch__/5", - "line": 62, - "module": "Phoenix.Endpoint.RenderErrors", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, kind, reason, stack, opts", - "arity": 5, - "function": "instrument_render_and_send", - "module": "Phoenix.Endpoint.RenderErrors" - } - }, - { - "caller": { - "function": "validate_args!/3", - "line": 408, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "validate_args!/3", - "line": 403, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "validate_args!/3", - "line": 397, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "schema", - "arity": 1, - "function": "valid?", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "validate_args!/3", - "line": 392, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "valid?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "validate_args!/3", - "line": 371, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "schema_name_or_plural", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "run/1", - "line": 134, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 135, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, paths, binding)", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 131, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_code_injection", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 130, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/1", - "line": 128, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 119, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 140, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 141, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "files_to_be_generated(context)", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "prompt_for_code_injection/1", - "line": 448, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "merge_with_existing_context?", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "prompt_for_code_injection/1", - "line": 448, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "pre_existing?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "print_shell_instructions/1", - "line": 332, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "parse_opts/1", - "line": 166, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Keyword.merge([schema: true, context: true], opts), opts[:context_app]", - "arity": 2, - "function": "put_context_app", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "merge_with_existing_context?/1", - "line": 462, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_count, \"files\"", - "arity": 2, - "function": "singularize", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "merge_with_existing_context?/1", - "line": 461, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "function_count, \"functions\"", - "arity": 2, - "function": "singularize", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "merge_with_existing_context?/1", - "line": 456, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "file_count", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "merge_with_existing_context?/1", - "line": 455, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "function_count", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "maybe_print_unimplemented_fixture_functions/1", - "line": 292, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, 2", - "arity": 2, - "function": "indent", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 242, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, <<\"priv/templates/phx.gen.context/\"::binary, String.Chars.to_string(file)::binary>>, binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 243, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(\n paths,\n <<\"priv/templates/phx.gen.context/\"::binary, String.Chars.to_string(file)::binary>>,\n binding\n), test_file, binding", - "arity": 3, - "function": "inject_eex_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 232, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_test_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_test_fixture/3", - "line": 272, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "maybe_print_unimplemented_fixture_functions", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_test_fixture/3", - "line": 268, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_test_fixture/3", - "line": 269, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding)", - "arity": 1, - "function": "prepend_newline", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_test_fixture/3", - "line": 270, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.context/fixtures.ex\", binding)\n), test_fixtures_file, binding", - "arity": 3, - "function": "inject_eex_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_test_fixture/3", - "line": 265, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_test_fixtures_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_schema_access/3", - "line": 211, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "schema_access_template", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_schema_access/3", - "line": 210, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, <<\"priv/templates/phx.gen.context/\"::binary,\n String.Chars.to_string(schema_access_template(context))::binary>>, binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_schema_access/3", - "line": 214, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(\n paths,\n <<\"priv/templates/phx.gen.context/\"::binary,\n String.Chars.to_string(schema_access_template(context))::binary>>,\n binding\n), file, binding", - "arity": 3, - "function": "inject_eex_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_schema_access/3", - "line": 207, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_context_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_eex_before_final_end/3", - "line": 325, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "<>, file_path", - "arity": 2, - "function": "write_file", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 180, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "ensure_test_fixtures_file_exists/3", - "line": 255, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.context/fixtures_module.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "ensure_test_fixtures_file_exists/3", - "line": 252, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "pre_existing_test_fixtures?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "ensure_test_file_exists/3", - "line": 226, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.context/context_test.exs\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "ensure_test_file_exists/3", - "line": 223, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "pre_existing_tests?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "ensure_context_file_exists/3", - "line": 201, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.context/context.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "ensure_context_file_exists/3", - "line": 198, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "pre_existing?", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 191, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_test_fixture", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 190, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_tests", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 189, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_schema_access", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 188, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema, paths, binding", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "build/2", - "line": 156, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context_name, schema, opts", - "arity": 3, - "function": "new", - "module": "Mix.Phoenix.Context" - } - }, - { - "caller": { - "function": "build/2", - "line": 155, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "[schema_module, plural | schema_args], opts, help", - "arity": 3, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Schema" - } - }, - { - "caller": { - "function": "build/2", - "line": 152, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parsed, optional, help", - "arity": 3, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "build/2", - "line": 149, - "module": "Mix.Tasks.Phx.Gen.Context", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "parse_opts", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "plug/4", - "line": 196, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "guards", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/4", - "line": 190, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, caller", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/4", - "line": 183, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "plug, caller", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/4", - "line": 179, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "plug_init_mode", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "plug/2", - "line": 174, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, opts, guards, __CALLER__", - "arity": 4, - "function": "plug", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/2", - "line": 176, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, opts, true, __CALLER__", - "arity": 4, - "function": "plug", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/1", - "line": 164, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, [], guards, __CALLER__", - "arity": 4, - "function": "plug", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "plug/1", - "line": 166, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, [], true, __CALLER__", - "arity": 4, - "function": "plug", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "escape_guards/1", - "line": 210, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "right", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "escape_guards/1", - "line": 210, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "left", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "escape_guards/1", - "line": 213, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "right", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "escape_guards/1", - "line": 213, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "left", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "escape_guards/1", - "line": 216, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "escape_guards", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "__catch__/5", - "line": 152, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "args", - "arity": 1, - "function": "exception", - "module": "Phoenix.ActionClauseError" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 88, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "Module.get_attribute(env.module(), :phoenix_fallback)", - "arity": 1, - "function": "build_fallback", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 82, - "module": "Phoenix.Controller.Pipeline", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "kind": "defmacro" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "plug_init_mode", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "validate_actions/3", - "line": 69, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "singleton", - "arity": 1, - "function": "default_actions", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "extract_actions/2", - "line": 64, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "singleton", - "arity": 1, - "function": "default_actions", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "extract_actions/2", - "line": 61, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":except, singleton, except", - "arity": 3, - "function": "validate_actions", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "extract_actions/2", - "line": 57, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":only, singleton, only", - "arity": 3, - "function": "validate_actions", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "build/3", - "line": 47, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Router.Resource, %{\n path: path,\n actions: actions,\n param: param,\n route: route,\n member: member,\n collection: collection,\n controller: controller,\n singleton: singleton\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "build/3", - "line": 40, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "options, singleton", - "arity": 2, - "function": "extract_actions", - "module": "Phoenix.Router.Resource" - } - }, - { - "caller": { - "function": "build/3", - "line": 34, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "controller, \"Controller\"", - "arity": 2, - "function": "resource_name", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "build/3", - "line": 31, - "module": "Phoenix.Router.Resource", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "path", - "arity": 1, - "function": "validate_path", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "from_map!/1", - "line": 35, - "module": "Phoenix.Socket.Message", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "<<\"missing key \"::binary, Kernel.inspect(err.key())::binary>>", - "arity": 1, - "function": "exception", - "module": "Phoenix.Socket.InvalidMessageError" - } - }, - { - "caller": { - "function": "from_map!/1", - "line": 26, - "module": "Phoenix.Socket.Message", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{\n topic: :maps.get(\"topic\", map),\n event: :maps.get(\"event\", map),\n payload: :maps.get(\"payload\", map),\n ref: :maps.get(\"ref\", map),\n join_ref: Map.get(map, \"join_ref\")\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.Message" - } - }, - { - "caller": { - "function": "web_test_path/2", - "line": 269, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "web_path/2", - "line": 211, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "modules/0", - "line": 180, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "beam_to_module", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inflect/1", - "line": 112, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "singular", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "inflect/1", - "line": 108, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "scoped", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "inflect/1", - "line": 107, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "singular", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "inflect/1", - "line": 106, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "base", - "arity": 1, - "function": "web_module", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inflect/1", - "line": 105, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "eval_from/3", - "line": 12, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "capture, source_file_path", - "arity": 2, - "function": "to_app_source", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_from/4", - "line": 35, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 2, - "function": "maybe_eex_gettext", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_from/4", - "line": 34, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 2, - "function": "maybe_heex_attr_gettext", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_from/4", - "line": 30, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "capture, source_dir", - "arity": 2, - "function": "to_app_source", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_test_path/2", - "line": 250, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ctx_app, Path.join([\"test\", String.Chars.to_string(ctx_app), rel_path])", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_lib_path/2", - "line": 243, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ctx_app, Path.join([\"lib\", String.Chars.to_string(ctx_app), rel_path])", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_base/1", - "line": 156, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "app_base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_app_path/2", - "line": 232, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ctx_app, this_app", - "arity": 2, - "function": "mix_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_app_path/2", - "line": 224, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_app/0", - "line": 259, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "this_app", - "arity": 1, - "function": "fetch_context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "context_app/0", - "line": 257, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "base/0", - "line": 145, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "base/0", - "line": 145, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app()", - "arity": 1, - "function": "app_base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "app_base/1", - "line": 161, - "module": "Mix.Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "String.Chars.to_string(app)", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "exception/1", - "line": 254, - "module": "Phoenix.Socket.InvalidMessageError", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[message: msg]", - "arity": 1, - "function": "exception", - "module": "Phoenix.Socket.InvalidMessageError" - } - }, - { - "caller": { - "function": "init/1", - "line": 50, - "module": "Phoenix.Socket.PoolSupervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "endpoint, {:socket, name}, ref", - "arity": 3, - "function": "permanent", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 760, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path, config", - "arity": 2, - "function": "socket_path", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 758, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "longpoll, Phoenix.Transports.LongPoll", - "arity": 2, - "function": "load_config", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 757, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "longpoll, opts[:auth_token]", - "arity": 2, - "function": "put_auth_token", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 749, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path, config", - "arity": 2, - "function": "socket_path", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 747, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "websocket, Phoenix.Transports.WebSocket", - "arity": 2, - "function": "load_config", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 746, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "websocket, opts[:auth_token]", - "arity": 2, - "function": "put_auth_token", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 735, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Keyword.get(opts, :longpoll, false), :erlang.++(common_config, [:window_ms, :pubsub_timeout_ms, :crypto])", - "arity": 2, - "function": "maybe_validate_keys", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "socket_paths/4", - "line": 720, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Keyword.get(opts, :websocket, true), :erlang.++(common_config, [\n :timeout,\n :max_frame_size,\n :fullsweep_after,\n :compress,\n :subprotocols,\n :error_handler\n])", - "arity": 2, - "function": "maybe_validate_keys", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "server?/2", - "line": 1092, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "otp_app, endpoint", - "arity": 2, - "function": "server?", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 415, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "server", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 414, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "plug", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 413, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "pubsub", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 412, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "config", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 649, - "module": "Phoenix.Endpoint", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "module, path, socket, socket_opts", - "arity": 4, - "function": "socket_paths", - "module": "Phoenix.Endpoint" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 10, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "map", - "arity": 1, - "function": "encode_v1_fields_only", - "module": "Phoenix.Socket.V1.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 9, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{join_ref: nil, ref: nil, topic: msg.topic(), event: msg.event(), payload: msg.payload()}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.V1.JSONSerializer" - } - }, - { - "caller": { - "function": "encode_v1_fields_only/1", - "line": 45, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 22, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "map", - "arity": 1, - "function": "encode_v1_fields_only", - "module": "Phoenix.Socket.V1.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 15, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{\n join_ref: nil,\n topic: reply.topic(),\n event: \"phx_reply\",\n ref: reply.ref(),\n payload: %{status: reply.status(), response: reply.payload()}\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.V1.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 26, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "map", - "arity": 1, - "function": "encode_v1_fields_only", - "module": "Phoenix.Socket.V1.JSONSerializer" - } - }, - { - "caller": { - "function": "decode!/2", - "line": 35, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "payload", - "arity": 1, - "function": "from_map!", - "module": "Phoenix.Socket.Message" - } - }, - { - "caller": { - "function": "decode!/2", - "line": 31, - "module": "Phoenix.Socket.V1.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "format_route/3", - "line": 112, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "router, Map.get(route, :helper)", - "arity": 2, - "function": "route_name", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format_route/3", - "line": 111, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "verb", - "arity": 1, - "function": "verb_name", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format_endpoint/2", - "line": 32, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, widths", - "arity": 2, - "function": "format_longpoll", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format_endpoint/2", - "line": 32, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, widths", - "arity": 2, - "function": "format_websocket", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format/2", - "line": 19, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, column_widths", - "arity": 2, - "function": "format_endpoint", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format/2", - "line": 18, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "capture, router, column_widths", - "arity": 3, - "function": "format_route", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "format/2", - "line": 15, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "router, routes, endpoint", - "arity": 3, - "function": "calculate_column_widths", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "calculate_column_widths/3", - "line": 95, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "socket_verbs", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "calculate_column_widths/3", - "line": 85, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "router, helper", - "arity": 2, - "function": "route_name", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "calculate_column_widths/3", - "line": 83, - "module": "Phoenix.Router.ConsoleFormatter", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "verb", - "arity": 1, - "function": "verb_name", - "module": "Phoenix.Router.ConsoleFormatter" - } - }, - { - "caller": { - "function": "terminate/2", - "line": 129, - "module": "Phoenix.Socket.PoolDrainer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{payload: nil, topic: nil, event: \"phx_drain\"}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.PoolDrainer" - } - }, - { - "caller": { - "function": "start/2", - "line": 26, - "module": "Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "install", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "start/2", - "line": 22, - "module": "Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "filter", - "arity": 1, - "function": "compile_filter", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "start/2", - "line": 14, - "module": "Phoenix", - "file": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "warn_on_missing_json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "run/1", - "line": 85, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "keyfile, certfile", - "arity": 2, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "run/1", - "line": 70, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "2048, name, hostnames", - "arity": 3, - "function": "certificate_and_key", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "print_shell_instructions/2", - "line": 124, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "base", - "arity": 1, - "function": "web_module", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/2", - "line": 117, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "print_shell_instructions/2", - "line": 116, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new_cert/3", - "line": 264, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "public_key, hostnames", - "arity": 2, - "function": "extensions", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "new_cert/3", - "line": 258, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "common_name", - "arity": 1, - "function": "rdn", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "new_cert/3", - "line": 252, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "common_name", - "arity": 1, - "function": "rdn", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "new_cert/3", - "line": 0, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "64", - "arity": 1, - "function": "size", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "extensions/2", - "line": 296, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "public_key", - "arity": 1, - "function": "key_identifier", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "certificate_and_key/3", - "line": 109, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "public_key, name, hostnames", - "arity": 3, - "function": "new_cert", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "certificate_and_key/3", - "line": 105, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "private_key", - "arity": 1, - "function": "extract_public_key", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "certificate_and_key/3", - "line": 91, - "module": "Mix.Tasks.Phx.Gen.Cert", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key_size, 65537", - "arity": 2, - "function": "generate_rsa_key", - "module": "Mix.Tasks.Phx.Gen.Cert" - } - }, - { - "caller": { - "function": "to_param/1", - "line": 63, - "module": "Phoenix.Param", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "term", - "arity": 1, - "function": "impl_for!", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "impl_for!/1", - "line": 1, - "module": "Phoenix.Param", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "data", - "arity": 1, - "function": "impl_for", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "impl_for/1", - "line": 1, - "module": "Phoenix.Param", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "struct", - "arity": 1, - "function": "struct_impl_for", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "maybe_auth_token_from_header/2", - "line": 116, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_private(conn, :phoenix_transport_auth_token, token), actual_subprotocols", - "arity": 2, - "function": "set_actual_subprotocols", - "module": "Phoenix.Transports.WebSocket" - } - }, - { - "caller": { - "function": "call/2", - "line": 65, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn, endpoint, keys, Keyword.take(opts, [:check_csrf])", - "arity": 4, - "function": "connect_info", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 52, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Plug.Conn.fetch_query_params(conn), endpoint, opts", - "arity": 3, - "function": "code_reload", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 53, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts), opts[:transport_log]", - "arity": 2, - "function": "transport_log", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 54, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n), handler, endpoint, opts", - "arity": 4, - "function": "check_origin", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 55, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts\n), opts[:auth_token]", - "arity": 2, - "function": "maybe_auth_token_from_header", - "module": "Phoenix.Transports.WebSocket" - } - }, - { - "caller": { - "function": "call/2", - "line": 56, - "module": "Phoenix.Transports.WebSocket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "maybe_auth_token_from_header(\n Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(Plug.Conn.fetch_query_params(conn), endpoint, opts),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts\n ),\n opts[:auth_token]\n), subprotocols", - "arity": 2, - "function": "check_subprotocols", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "event_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "topic_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 14, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg.event(), :event, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 13, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg.topic(), :topic, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "fastlane!/1", - "line": 29, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "status_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "topic_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ref_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "join_ref_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 45, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "status, :status, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 44, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "reply.topic(), :topic, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 43, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ref, :ref, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 42, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "join_ref, :join_ref, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 72, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "event_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "topic_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "join_ref_size", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 0, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "8", - "arity": 1, - "function": "size", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 79, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg.event(), :event, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 78, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg.topic(), :topic, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 77, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "join_ref, :join_ref, 255", - "arity": 3, - "function": "byte_size!", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "encode!/1", - "line": 97, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "decode_text/1", - "line": 115, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{topic: topic, event: event, payload: payload, ref: ref, join_ref: join_ref}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "decode_text/1", - "line": 113, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "decode_binary/1", - "line": 136, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{topic: topic, event: event, payload: {:binary, data}, ref: ref, join_ref: join_ref}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "decode!/2", - "line": 108, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "raw_message", - "arity": 1, - "function": "decode_binary", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "decode!/2", - "line": 107, - "module": "Phoenix.Socket.V2.JSONSerializer", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "raw_message", - "arity": 1, - "function": "decode_text", - "module": "Phoenix.Socket.V2.JSONSerializer" - } - }, - { - "caller": { - "function": "verify/4", - "line": 222, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "get_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "sign/4", - "line": 135, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "get_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "get_key_base/1", - "line": 253, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "endpoint_module", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "get_key_base/1", - "line": 253, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Controller.endpoint_module(conn)", - "arity": 1, - "function": "get_endpoint_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "get_key_base/1", - "line": 256, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "get_endpoint_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "get_key_base/1", - "line": 259, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "get_endpoint_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "encrypt/4", - "line": 161, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "get_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "decrypt/4", - "line": 246, - "module": "Phoenix.Token", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "get_key_base", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "next_task/1", - "line": 588, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "next, ref", - "arity": 2, - "function": "send_continue", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "next_task/1", - "line": 587, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Task, %{}", - "arity": 2, - "function": "%", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "merge_diff/3", - "line": 661, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "updated_topics, topic", - "arity": 2, - "function": "remove_topic", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "merge_diff/3", - "line": 660, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "updated_topics, topic", - "arity": 2, - "function": "topic_presences_count", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "merge_diff/3", - "line": 657, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 2, - "function": "handle_leave", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "merge_diff/3", - "line": 656, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 2, - "function": "handle_join", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "merge_diff/3", - "line": 652, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "topics, topic", - "arity": 2, - "function": "add_new_topic", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "list/2", - "line": 552, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Tracker.list(module, topic)", - "arity": 1, - "function": "group", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_leave/2", - "line": 673, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "topics, topic, left_key, presence", - "arity": 4, - "function": "remove_presence_or_metas", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_join/2", - "line": 669, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "topics, topic, joined_key, joined_metas", - "arity": 4, - "function": "add_new_presence_or_metas", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 544, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "new_state", - "arity": 1, - "function": "next_task", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 539, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, computed_diffs", - "arity": 2, - "function": "do_handle_metas", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 528, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: \"presence_diff\", payload: presence_diff}", - "arity": 2, - "function": "%", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 524, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Task, %{ref: ^task_ref}", - "arity": 2, - "function": "%", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "handle_diff/2", - "line": 518, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, diff", - "arity": 2, - "function": "async_merge", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "do_handle_metas/2", - "line": 598, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "acc.topics(), topic, presence_diff", - "arity": 3, - "function": "merge_diff", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "async_merge/2", - "line": 641, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "new_task, ref", - "arity": 2, - "function": "send_continue", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "async_merge/2", - "line": 629, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "leaves", - "arity": 1, - "function": "group", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "async_merge/2", - "line": 628, - "module": "Phoenix.Presence", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "joins", - "arity": 1, - "function": "group", - "module": "Phoenix.Presence" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 131, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route.verb()", - "arity": 1, - "function": "verb_match", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 130, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route", - "arity": 1, - "function": "build_prepare", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 129, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "build_path_params", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 128, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route.hosts()", - "arity": 1, - "function": "build_host_match", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 127, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route", - "arity": 1, - "function": "build_dispatch", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "exprs/1", - "line": 122, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route", - "arity": 1, - "function": "build_path_and_binding", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "build_prepare/1", - "line": 175, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":assigns, route.assigns()", - "arity": 2, - "function": "build_prepare_expr", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "build_prepare/1", - "line": 174, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":private, route.private()", - "arity": 2, - "function": "build_prepare_expr", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "build_prepare/1", - "line": 173, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_params", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "build_path_and_binding/1", - "line": 153, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "segments", - "arity": 1, - "function": "rewrite_segments", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "build/14", - "line": 100, - "module": "Phoenix.Router.Route", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Router.Route, %{\n kind: kind,\n verb: verb,\n path: path,\n hosts: hosts,\n private: private,\n plug: plug,\n plug_opts: plug_opts,\n helper: helper,\n pipe_through: pipe_through,\n assigns: assigns,\n line: line,\n metadata: metadata,\n trailing_slash?: trailing_slash?,\n warn_on_verify?: warn_on_verify?\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "run_compilers/4", - "line": 406, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, args, status, diagnostics", - "arity": 4, - "function": "run_compilers", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "run_compilers/4", - "line": 405, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, args, :ok, diagnostics", - "arity": 4, - "function": "run_compilers", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "run_compilers/4", - "line": 400, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "compiler, args", - "arity": 2, - "function": "run_compiler", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "run_compiler/2", - "line": 411, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Task.run(<<\"compile.\"::binary, String.Chars.to_string(compiler)::binary>>, args), compiler", - "arity": 2, - "function": "normalize", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "purge_modules/1", - "line": 366, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":erlang.binary_to_atom(module)", - "arity": 1, - "function": "purge_module", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "proxy_io/1", - "line": 386, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "proxy_gl", - "arity": 1, - "function": "stop", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "proxy_io/1", - "line": 382, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "start", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "mix_compile_unless_stale_config/5", - "line": 305, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "compilers, compile_args, config, path", - "arity": 4, - "function": "mix_compile", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile_unless_stale_config/5", - "line": 302, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Path.join(Mix.Project.app_path(config), \"ebin\")", - "arity": 1, - "function": "purge_modules", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile_project/7", - "line": 287, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "compilers, compile_args, timestamp, path, purge_fallback?", - "arity": 5, - "function": "mix_compile_unless_stale_config", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile_deps/7", - "line": 270, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "compilers, compile_args, timestamp, path, purge_fallback?", - "arity": 5, - "function": "mix_compile_unless_stale_config", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile/6", - "line": 246, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "purge_modules", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile/6", - "line": 231, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "config[:app], apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", - "arity": 7, - "function": "mix_compile_project", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile/6", - "line": 221, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Dep.cached(), apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", - "arity": 7, - "function": "mix_compile_deps", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile/4", - "line": 341, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": ":erlang.group_leader(), diagnostics", - "arity": 2, - "function": "diagnostics", - "module": "Phoenix.CodeReloader.Proxy" - } - }, - { - "caller": { - "function": "mix_compile/4", - "line": 338, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "compilers, args, :noop, []", - "arity": 4, - "function": "run_compilers", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "mix_compile/4", - "line": 337, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "config, fn -> run_compilers(compilers, args, :noop, []) end", - "arity": 2, - "function": "with_logger_app", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "load_backup/1", - "line": 163, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":code.which(mod)", - "arity": 1, - "function": "read_backup", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "init/1", - "line": 34, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "timestamp", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 53, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":os.type()", - "arity": 1, - "function": "os_symlink", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 47, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "can_symlink?", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 113, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "timestamp", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 108, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "backup", - "arity": 1, - "function": "write_backup", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 88, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?", - "arity": 6, - "function": "mix_compile", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 85, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "fn ->\n try do\n task_loaded = Code.ensure_loaded(Mix.Task)\n mix_compile(task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?)\n catch\n :exit, {:shutdown, 1} ->\n :error\n\n kind, reason ->\n IO.puts(Exception.format(kind, reason, __STACKTRACE__))\n :error\n end\nend", - "arity": 1, - "function": "proxy_io", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 82, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "load_backup", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 73, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "apps", - "arity": 1, - "function": "purge", - "module": "Phoenix.CodeReloader.MixListener" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 76, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "warn_missing_mix_listener", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 72, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "started?", - "module": "Phoenix.CodeReloader.MixListener" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 70, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "fn ->\n purge_fallback? =\n case Phoenix.CodeReloader.MixListener.started?() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n warn_missing_mix_listener()\n true\n\n _ ->\n Phoenix.CodeReloader.MixListener.purge(apps)\n false\n end\n\n backup = load_backup(endpoint)\n\n {res, out} =\n proxy_io(fn ->\n try do\n task_loaded = Code.ensure_loaded(Mix.Task)\n mix_compile(task_loaded, compilers, apps, args, state.timestamp(), purge_fallback?)\n catch\n :exit, {:shutdown, 1} ->\n :error\n\n kind, reason ->\n IO.puts(Exception.format(kind, reason, __STACKTRACE__))\n :error\n end\n end)\n\n {backup, res, out}\nend", - "arity": 1, - "function": "with_build_lock", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 67, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "[from], endpoint", - "arity": 2, - "function": "all_waiting", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 64, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "default_reloadable_apps", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "all_waiting/2", - "line": 180, - "module": "Phoenix.CodeReloader.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "[from | acc], endpoint", - "arity": 2, - "function": "all_waiting", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "reply/6", - "line": 262, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{topic: topic, join_ref: join_ref, ref: ref, status: status, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "push/6", - "line": 250, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{ref: nil, join_ref: join_ref, topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "local_broadcast_from/5", - "line": 233, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "local_broadcast/4", - "line": 216, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "join/4", - "line": 20, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 3, - "function": "start_child", - "module": "Phoenix.Socket.PoolSupervisor" - } - }, - { - "caller": { - "function": "handle_result/2", - "line": 455, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reason", - "arity": 2, - "function": "send_socket_close", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_result/2", - "line": 454, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reason", - "arity": 2, - "function": "send_socket_close", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_result/2", - "line": 453, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reason", - "arity": 2, - "function": "send_socket_close", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_reply/2", - "line": 528, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket.transport_pid(), socket.join_ref(), socket.ref(), socket.topic(), {status, payload}, socket.serializer()", - "arity": 6, - "function": "reply", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_reply/2", - "line": 539, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, {status, %{}}", - "arity": 2, - "function": "handle_reply", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 315, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "channel, topic, auth_payload, socket", - "arity": 4, - "function": "channel_join", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 324, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "{:stop, {:shutdown, :left}, :ok, Map.update!(socket, :ref, fn _ -> ref end)}", - "arity": 1, - "function": "handle_in", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 336, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "result", - "arity": 1, - "function": "handle_in", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 353, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket.channel.handle_out(event, payload, socket), :handle_out", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 369, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket.channel.handle_info(msg, socket), :handle_info", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 371, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":handle_info, 2, msg, channel", - "arity": 4, - "function": "warn_unexpected_msg", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_in/1", - "line": 514, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "handle_reply", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_in/1", - "line": 520, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "{:stop, reason, socket}, :handle_in", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_in/1", - "line": 519, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "handle_reply", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_in/1", - "line": 524, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "other, :handle_in", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_cast/2", - "line": 295, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket.channel.handle_cast(msg, socket), :handle_cast", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_call/3", - "line": 283, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket.channel.handle_call(msg, from, socket), :handle_call", - "arity": 2, - "function": "handle_result", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "channel_join/4", - "line": 406, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, channel, topic", - "arity": 3, - "function": "init_join", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "channel_join/4", - "line": 403, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, channel, topic", - "arity": 3, - "function": "init_join", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from!/5", - "line": 199, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from/5", - "line": 182, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast!/4", - "line": 165, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast/4", - "line": 148, - "module": "Phoenix.Channel.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Broadcast, %{topic: topic, event: event, payload: payload}", - "arity": 2, - "function": "%", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "publish_reply/2", - "line": 141, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "publish_reply/2", - "line": 141, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state, Phoenix.json_library().encode_to_iodata!(reply)", - "arity": 2, - "function": "publish_reply", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "publish_reply/2", - "line": 145, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state", - "arity": 1, - "function": "notify_client_now_available", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "notify_client_now_available/1", - "line": 151, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {:now_available, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "init/1", - "line": 37, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state.window_ms()", - "arity": 1, - "function": "schedule_inactive_shutdown", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "init/1", - "line": 32, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now_ms", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 65, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {:error, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 60, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {:ok, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 56, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, reply", - "arity": 2, - "function": "publish_reply", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 55, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {status, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 71, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {:subscribe, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 82, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now_ms", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 81, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, client_ref, {:messages, Enum.reverse(buffer), ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 78, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now_ms", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 100, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state.window_ms()", - "arity": 1, - "function": "schedule_inactive_shutdown", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 97, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now_ms", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "handle_info/2", - "line": 111, - "module": "Phoenix.Transports.LongPoll.Server", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, reply", - "arity": 2, - "function": "publish_reply", - "module": "Phoenix.Transports.LongPoll.Server" - } - }, - { - "caller": { - "function": "raise_route_error/6", - "line": 317, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, fun, arity, action, routes", - "arity": 5, - "function": "invalid_param_error", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "raise_route_error/6", - "line": 314, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "<<\"no function clause for \"::binary, Kernel.inspect(mod)::binary, \".\"::binary,\n String.Chars.to_string(fun)::binary, \"/\"::binary, String.Chars.to_string(arity)::binary,\n \" and action \"::binary, Kernel.inspect(action)::binary>>, fun, routes", - "arity": 3, - "function": "invalid_route_error", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "raise_route_error/6", - "line": 310, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "<<\"no action \"::binary, Kernel.inspect(action)::binary, \" for \"::binary,\n Kernel.inspect(mod)::binary, \".\"::binary, String.Chars.to_string(fun)::binary, \"/\"::binary,\n String.Chars.to_string(arity)::binary>>, fun, routes", - "arity": 3, - "function": "invalid_route_error", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "expand_segments/2", - "line": 366, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "[h], acc", - "arity": 2, - "function": "expand_segments", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "expand_segments/2", - "line": 371, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "t, {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n :elixir_quote.shallow_validate_ast(acc),\n :elixir_quote.shallow_validate_ast(<<\"/\"::binary, h::binary>>)\n ]}", - "arity": 2, - "function": "expand_segments", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "expand_segments/2", - "line": 375, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "t, {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n :elixir_quote.shallow_validate_ast(acc),\n {:<>, [context: Phoenix.Router.Helpers, imports: [{2, Kernel}]],\n [\n \"/\",\n {{:., [], [:elixir_quote.shallow_validate_ast(Phoenix.Router.Helpers), :encode_param]}, [],\n [{:to_param, [], [:elixir_quote.shallow_validate_ast(h)]}]}\n ]}\n ]}", - "arity": 2, - "function": "expand_segments", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "expand_segments/1", - "line": 355, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "segments, \"\"", - "arity": 2, - "function": "expand_segments", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "define/2", - "line": 29, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "defhelper_catch_all", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "define/2", - "line": 27, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route, exprs", - "arity": 2, - "function": "defhelper", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "defhelper/2", - "line": 256, - "module": "Phoenix.Router.Helpers", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "exprs.path()", - "arity": 1, - "function": "expand_segments", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "write_manifest/3", - "line": 116, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "save_manifest/4", - "line": 110, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "latest, digests, output_path", - "arity": 3, - "function": "write_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "save_manifest/4", - "line": 109, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "files", - "arity": 1, - "function": "generate_digests", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "remove_files/2", - "line": 403, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, output_path", - "arity": 2, - "function": "remove_compressed_file", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "remove_compressed_files/2", - "line": 408, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, output_path", - "arity": 2, - "function": "remove_compressed_file", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "remove_compressed_file/2", - "line": 412, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "compressed_extensions", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "relative_digested_path/2", - "line": 306, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digested_path", - "arity": 1, - "function": "relative_digested_path", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "relative_digested_path/2", - "line": 309, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digested_path", - "arity": 1, - "function": "relative_digested_path", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "maybe_fixup_sourcemap/2", - "line": 54, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "sourcemap, files", - "arity": 2, - "function": "fixup_sourcemap", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "load_manifest/1", - "line": 93, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "load_manifest/1", - "line": 94, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.json_library().decode!(File.read!(manifest_path)), output_path", - "arity": 2, - "function": "migrate_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "load_compile_digests/1", - "line": 83, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "output_path", - "arity": 1, - "function": "load_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "generate_latest/1", - "line": 77, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture.relative_path(), capture.digested_filename()", - "arity": 2, - "function": "manifest_join", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "generate_latest/1", - "line": 76, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture.relative_path(), capture.filename()", - "arity": 2, - "function": "manifest_join", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "generate_digests/1", - "line": 139, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture", - "arity": 1, - "function": "build_digest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "generate_digests/1", - "line": 138, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture.relative_path(), capture.digested_filename()", - "arity": 2, - "function": "manifest_join", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "fixup_sourcemaps/1", - "line": 49, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, files", - "arity": 2, - "function": "maybe_fixup_sourcemap", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "filter_files/1", - "line": 45, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, input_path", - "arity": 2, - "function": "map_file", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "filter_files/1", - "line": 44, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture", - "arity": 1, - "function": "compiled_file?", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "files_to_clean/4", - "line": 380, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "versions, max_age, keep", - "arity": 3, - "function": "versions_to_clean", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "files_to_clean/4", - "line": 379, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digests", - "arity": 1, - "function": "group_by_logical_path", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_url/4", - "line": 278, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digested_path, with_vsn?", - "arity": 2, - "function": "relative_digested_path", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_url/4", - "line": 294, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, digested_path, with_vsn?", - "arity": 3, - "function": "absolute_digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_url/4", - "line": 285, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "URI, %{scheme: nil, host: nil}", - "arity": 2, - "function": "%", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_contents/3", - "line": 237, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, latest", - "arity": 2, - "function": "digest_javascript_map_asset_references", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_contents/3", - "line": 236, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, latest", - "arity": 2, - "function": "digest_javascript_asset_references", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digested_contents/3", - "line": 235, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file, latest, with_vsn?", - "arity": 3, - "function": "digest_stylesheet_asset_references", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digest_stylesheet_asset_references/3", - "line": 255, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, file, latest, with_vsn?", - "arity": 4, - "function": "digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digest_stylesheet_asset_references/3", - "line": 252, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, file, latest, with_vsn?", - "arity": 4, - "function": "digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digest_javascript_map_asset_references/2", - "line": 272, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, file, latest, false", - "arity": 4, - "function": "digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "digest_javascript_asset_references/2", - "line": 264, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, file, latest, false", - "arity": 4, - "function": "digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compiled_file?/1", - "line": 161, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "compressed_extensions", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 33, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "capture, output_path", - "arity": 2, - "function": "write_to_disk", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 30, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "digested_files, latest, digests, output_path", - "arity": 4, - "function": "save_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 28, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "capture, latest, with_vsn?", - "arity": 3, - "function": "digested_contents", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 27, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "output_path", - "arity": 1, - "function": "load_compile_digests", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 26, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "files", - "arity": 1, - "function": "generate_latest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 25, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "files", - "arity": 1, - "function": "fixup_sourcemaps", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "compile/3", - "line": 24, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "input_path", - "arity": 1, - "function": "filter_files", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean_all/1", - "line": 369, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "remove_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean_all/1", - "line": 368, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "logical_paths, path", - "arity": 2, - "function": "remove_compressed_files", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean_all/1", - "line": 367, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "files, path", - "arity": 2, - "function": "remove_files", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean_all/1", - "line": 359, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "digests", - "arity": 1, - "function": "group_by_logical_path", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean_all/1", - "line": 358, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "load_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean/4", - "line": 340, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "latest, Map.drop(digests, files), path", - "arity": 3, - "function": "write_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean/4", - "line": 339, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "files, path", - "arity": 2, - "function": "remove_files", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean/4", - "line": 338, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "latest, digests, :erlang.-(now, age), keep", - "arity": 4, - "function": "files_to_clean", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean/4", - "line": 337, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "load_manifest", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "clean/3", - "line": 335, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "build_digest/1", - "line": 147, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "now", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "build_digest/1", - "line": 146, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file.relative_path(), file.filename()", - "arity": 2, - "function": "manifest_join", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "absolute_digested_url/3", - "line": 315, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, digested_path", - "arity": 2, - "function": "absolute_digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "absolute_digested_url/3", - "line": 318, - "module": "Phoenix.Digester", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, digested_path", - "arity": 2, - "function": "absolute_digested_url", - "module": "Phoenix.Digester" - } - }, - { - "caller": { - "function": "subscribe_and_join!/4", - "line": 371, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, channel, topic, payload", - "arity": 4, - "function": "subscribe_and_join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "subscribe_and_join!/3", - "line": 359, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, payload", - "arity": 4, - "function": "subscribe_and_join!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "subscribe_and_join!/2", - "line": 353, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, %{}", - "arity": 4, - "function": "subscribe_and_join!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "subscribe_and_join/4", - "line": 407, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, channel, topic, payload", - "arity": 4, - "function": "join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "subscribe_and_join/3", - "line": 385, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, payload", - "arity": 4, - "function": "subscribe_and_join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "subscribe_and_join/2", - "line": 379, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, %{}", - "arity": 4, - "function": "subscribe_and_join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "stringify_kv/1", - "line": 709, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "v", - "arity": 1, - "function": "__stringify__", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "socket/4", - "line": 236, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "socket_module, socket_id, socket_assigns, options, __CALLER__", - "arity": 5, - "function": "socket", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "socket/2", - "line": 301, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "nil, id, assigns, [], __CALLER__", - "arity": 5, - "function": "socket", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "socket/1", - "line": 209, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "socket_module, nil, [], [], __CALLER__", - "arity": 5, - "function": "socket", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "socket/0", - "line": 295, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "nil, nil, [], [], __CALLER__", - "arity": 5, - "function": "socket", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "push/3", - "line": 475, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "payload", - "arity": 1, - "function": "__stringify__", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "push/3", - "line": 475, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{join_ref: nil, event: event, topic: socket.topic(), ref: ref, payload: __stringify__(payload)}", - "arity": 2, - "function": "%", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "leave/1", - "line": 488, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, \"phx_leave\", %{}", - "arity": 3, - "function": "push", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/4", - "line": 454, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pid", - "arity": 1, - "function": "socket", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "join/4", - "line": 451, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "socket, channel, message, :erlang.++([starter: starter], opts)", - "arity": 4, - "function": "join", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "join/4", - "line": 444, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket, %{transport: {Phoenix.ChannelTest, sup}}", - "arity": 2, - "function": "%", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/4", - "line": 441, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, topic", - "arity": 2, - "function": "match_topic_to_channel!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/4", - "line": 432, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "payload", - "arity": 1, - "function": "__stringify__", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/4", - "line": 430, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{\n join_ref: nil,\n event: \"phx_join\",\n payload: __stringify__(payload),\n topic: topic,\n ref: :erlang.unique_integer([:positive])\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/3", - "line": 417, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, payload", - "arity": 4, - "function": "join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "join/2", - "line": 412, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, nil, topic, %{}", - "arity": 4, - "function": "join", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "close/2", - "line": 502, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "socket.channel_pid(), timeout", - "arity": 2, - "function": "close", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from!/3", - "line": 527, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, transport_pid, topic, event, message", - "arity": 5, - "function": "broadcast_from!", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "broadcast_from/3", - "line": 519, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "pubsub_server, transport_pid, topic, event, message", - "arity": 5, - "function": "broadcast_from", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "__stringify__/1", - "line": 702, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "stringify_kv", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__stringify__/1", - "line": 704, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "__stringify__", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__socket__/5", - "line": 264, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "options", - "arity": 1, - "function": "fetch_test_supervisor!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__socket__/5", - "line": 260, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "first_socket!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__socket__/5", - "line": 257, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket, %{\n channel: nil,\n channel_pid: nil,\n join_ref: nil,\n joined: false,\n private: %{},\n ref: nil,\n topic: nil,\n assigns: Enum.into(assigns, %{}),\n endpoint: endpoint,\n handler:\n case socket do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n first_socket!(endpoint)\n\n x ->\n x\n end,\n id: id,\n pubsub_server: endpoint.config(:pubsub_server),\n serializer: Phoenix.ChannelTest.NoopSerializer,\n transport: {Phoenix.ChannelTest, fetch_test_supervisor!(options)},\n transport_pid: :erlang.self()\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__connect__/4", - "line": 342, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "__stringify__", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "__connect__/4", - "line": 340, - "module": "Phoenix.ChannelTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "options", - "arity": 1, - "function": "fetch_test_supervisor!", - "module": "Phoenix.ChannelTest" - } - }, - { - "caller": { - "function": "warmup_static/2", - "line": 424, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digests, Map.get(latest, key), with_vsn?", - "arity": 3, - "function": "static_cache", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup_static/2", - "line": 423, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "endpoint, {:__phoenix_static__, <<\"/\"::binary, key::binary>>}, fn _ -> {:cache, static_cache(digests, Map.get(latest, key), with_vsn?)} end", - "arity": 3, - "function": "cache", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "warmup_static/2", - "line": 419, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "endpoint, :cache_static_manifest_latest, latest", - "arity": 3, - "function": "put", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "warmup_persistent/1", - "line": 378, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "case static_url_config[:path] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"/\"\n x -> x\nend", - "arity": 1, - "function": "empty_string_if_root", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup_persistent/1", - "line": 377, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, static_url_config", - "arity": 2, - "function": "build_url", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup_persistent/1", - "line": 374, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "case url_config[:path] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"/\"\n x -> x\nend", - "arity": 1, - "function": "empty_string_if_root", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup_persistent/1", - "line": 373, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "case url_config[:host] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"localhost\"\n x -> x\nend", - "arity": 1, - "function": "host_to_binary", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup_persistent/1", - "line": 372, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, url_config", - "arity": 2, - "function": "build_url", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup/1", - "line": 356, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, manifest", - "arity": 2, - "function": "warmup_static", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup/1", - "line": 355, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "cache_static_manifest", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "warmup/1", - "line": 352, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "warmup_persistent", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "static_lookup/2", - "line": 289, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "raise_invalid_path", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "static_lookup/2", - "line": 301, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "raise_invalid_path", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "static_cache/3", - "line": 434, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digests[value][\"sha512\"]", - "arity": 1, - "function": "static_integrity", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "static_cache/3", - "line": 438, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "digests[value][\"sha512\"]", - "arity": 1, - "function": "static_integrity", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "start_link/3", - "line": 17, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf", - "arity": 2, - "function": "browser_open", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "start_link/3", - "line": 16, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf", - "arity": 2, - "function": "log_access_url", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "socket_children/3", - "line": 142, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, fun, [:erlang.++([endpoint: endpoint], opts)]", - "arity": 3, - "function": "apply_or_ignore", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "socket_children/3", - "line": 141, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conf, opts", - "arity": 2, - "function": "check_origin_or_csrf_checked!", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "server?/2", - "line": 216, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Application.get_env(otp_app, endpoint, [])", - "arity": 1, - "function": "server?", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "port_to_integer/1", - "line": 313, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "System.get_env(env_var)", - "arity": 1, - "function": "port_to_integer", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "log_access_url/2", - "line": 469, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conf", - "arity": 1, - "function": "server?", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 108, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf, server?", - "arity": 3, - "function": "watcher_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 107, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf, :drainer_spec", - "arity": 3, - "function": "socket_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 106, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf, server?", - "arity": 3, - "function": "server_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 105, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf, :child_spec", - "arity": 3, - "function": "socket_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 104, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, conf", - "arity": 2, - "function": "pubsub_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 103, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod", - "arity": 1, - "function": "warmup_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 102, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, secret_conf, default_conf", - "arity": 3, - "function": "config_children", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 99, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, mod, conf, :static_url", - "arity": 4, - "function": "warn_on_deprecated_system_env_tuples", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 98, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, mod, conf, :url", - "arity": 4, - "function": "warn_on_deprecated_system_env_tuples", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 97, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, mod, conf, :https", - "arity": 4, - "function": "warn_on_deprecated_system_env_tuples", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 96, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, mod, conf, :http", - "arity": 4, - "function": "warn_on_deprecated_system_env_tuples", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 92, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "check_symlinks", - "module": "Phoenix.CodeReloader.Server" - } - }, - { - "caller": { - "function": "init/1", - "line": 83, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conf", - "arity": 1, - "function": "server?", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 30, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "otp_app, mod, default_conf", - "arity": 3, - "function": "from_env", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "init/1", - "line": 29, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "otp_app, mod", - "arity": 2, - "function": "defaults", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "init/1", - "line": 29, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "defaults(otp_app, mod), opts", - "arity": 2, - "function": "merge", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "host_to_binary/1", - "line": 309, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "System.get_env(env_var)", - "arity": 1, - "function": "host_to_binary", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "defaults/2", - "line": 232, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "render_errors", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "config_change/3", - "line": 271, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "warmup", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "config_change/3", - "line": 270, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "endpoint, changed, removed", - "arity": 3, - "function": "config_change", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "cache_static_manifest/1", - "line": 456, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "build_url/2", - "line": 415, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "URI, %{\n authority: nil,\n fragment: nil,\n path: nil,\n query: nil,\n userinfo: nil,\n scheme: scheme,\n port: port,\n host: host\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "build_url/2", - "line": 407, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "case url[:port] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> port\n x -> x\nend", - "arity": 1, - "function": "port_to_integer", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "build_url/2", - "line": 406, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "case url[:host] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> \"localhost\"\n x -> x\nend", - "arity": 1, - "function": "host_to_binary", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "browser_open/2", - "line": 475, - "module": "Phoenix.Endpoint.Supervisor", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conf", - "arity": 1, - "function": "server?", - "module": "Phoenix.Endpoint.Supervisor" - } - }, - { - "caller": { - "function": "validate_hosts!/1", - "line": 199, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "host", - "arity": 1, - "function": "raise_invalid_host", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "validate_hosts!/1", - "line": 205, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "invalid", - "arity": 1, - "function": "raise_invalid_host", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "update_stack/2", - "line": 282, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module, :phoenix_router_scopes, fun", - "arity": 3, - "function": "update_attribute", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "update_pipes/2", - "line": 286, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module, :phoenix_pipeline_scopes, fun", - "arity": 3, - "function": "update_attribute", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "update_attribute/3", - "line": 300, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module, attr", - "arity": 2, - "function": "get_attribute", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "route/8", - "line": 64, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "line, kind, verb, path, top.hosts(), alias, plug_opts, as, top.pipes(), private, assigns, metadata, trailing_slash?, warn_on_verify?", - "arity": 14, - "function": "build", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "route/8", - "line": 59, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path, plug", - "arity": 2, - "function": "validate_forward!", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "route/8", - "line": 50, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "top, path, plug, alias?, as, private, assigns", - "arity": 7, - "function": "join", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "route/8", - "line": 42, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts, top", - "arity": 2, - "function": "deprecated_trailing_slash", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "route/8", - "line": 40, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "plug, \"Controller\"", - "arity": 2, - "function": "resource_name", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "route/8", - "line": 37, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "validate_path", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "route/8", - "line": 36, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 138, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, [path: path]", - "arity": 2, - "function": "push", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 174, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts, top", - "arity": 2, - "function": "deprecated_trailing_slash", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 165, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Router.Scope, %{\n path: :erlang.++(top.path(), path),\n alias: alias,\n as: as,\n hosts: hosts,\n pipes: top.pipes(),\n private: :maps.merge(top.private(), private),\n assigns: :maps.merge(top.assigns(), assigns),\n log: Keyword.get(opts, :log, top.log()),\n trailing_slash?: deprecated_trailing_slash(opts, top)\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 165, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, %Phoenix.Router.Scope{\n path: :erlang.++(top.path(), path),\n alias: alias,\n as: as,\n hosts: hosts,\n pipes: top.pipes(),\n private: :maps.merge(top.private(), private),\n assigns: :maps.merge(top.assigns(), assigns),\n log: Keyword.get(opts, :log, top.log()),\n trailing_slash?: deprecated_trailing_slash(opts, top)\n}", - "arity": 2, - "function": "put_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 163, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, fn stack -> [top | stack] end", - "arity": 2, - "function": "update_stack", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 156, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "val", - "arity": 1, - "function": "validate_hosts!", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 152, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "top, opts, :as, fn capture -> capture end", - "arity": 4, - "function": "append_unless_false", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 151, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "top, opts, :alias, &:erlang.atom_to_binary/1", - "arity": 4, - "function": "append_unless_false", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 146, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path", - "arity": 1, - "function": "validate_path", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "push/2", - "line": 142, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "pop/1", - "line": 225, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, top", - "arity": 2, - "function": "put_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "pop/1", - "line": 224, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, fn [top | stack] ->\n put_top(module, top)\n stack\nend", - "arity": 2, - "function": "update_stack", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "pipeline/2", - "line": 115, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, fn capture -> MapSet.put(capture, pipe) end", - "arity": 2, - "function": "update_pipes", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "pipe_through/2", - "line": 131, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, %{top | pipes: :erlang.++(pipes, new_pipes)}", - "arity": 2, - "function": "put_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "pipe_through/2", - "line": 123, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "join/7", - "line": 259, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "top, as", - "arity": 2, - "function": "join_as", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "join/7", - "line": 259, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "top, path", - "arity": 2, - "function": "join_path", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "join/7", - "line": 254, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "top, alias", - "arity": 2, - "function": "join_alias", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "init/1", - "line": 24, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Router.Scope, %{\n alias: [],\n as: [],\n assigns: %{},\n hosts: [],\n log: :debug,\n path: [],\n pipes: [],\n private: %{},\n trailing_slash?: false\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "get_top/1", - "line": 278, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "module, :phoenix_top_scopes", - "arity": 2, - "function": "get_attribute", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "full_path/2", - "line": 247, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "full_path/2", - "line": 242, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "expand_alias/2", - "line": 234, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module", - "arity": 1, - "function": "get_top", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "expand_alias/2", - "line": 234, - "module": "Phoenix.Router.Scope", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "get_top(module), alias", - "arity": 2, - "function": "join_alias", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "verify_token/3", - "line": 262, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "endpoint, :erlang.atom_to_binary(endpoint.config(:pubsub_server)), signed, opts[:crypto]", - "arity": 4, - "function": "verify", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "transport_dispatch/4", - "line": 121, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "server_ref", - "arity": 1, - "function": "client_ref", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "transport_dispatch/4", - "line": 121, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:dispatch, client_ref(server_ref), body, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "status_token_messages_json/3", - "line": 287, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, %{\n \"status\" =>\n case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\n end,\n \"token\" => token,\n \"messages\" => messages\n}", - "arity": 2, - "function": "send_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "status_json/1", - "line": 283, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, %{\n \"status\" =>\n case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\n end\n}", - "arity": 2, - "function": "send_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "sign_token/3", - "line": 253, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "endpoint, :erlang.atom_to_binary(endpoint.config(:pubsub_server)), data, opts[:crypto]", - "arity": 4, - "function": "sign", - "module": "Phoenix.Token" - } - }, - { - "caller": { - "function": "send_json/2", - "line": 293, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 206, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "server_ref", - "arity": 1, - "function": "client_ref", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 206, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:subscribe, client_ref(server_ref), ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 205, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref", - "arity": 2, - "function": "subscribe", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 200, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref", - "arity": 2, - "function": "unsubscribe", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 196, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint.config(:endpoint_id), id, pid, priv_topic", - "arity": 4, - "function": "server_ref", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "resume_session/4", - "line": 194, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, token, opts", - "arity": 3, - "function": "verify_token", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "publish/4", - "line": 104, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_status(conn, status)", - "arity": 1, - "function": "status_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "publish/4", - "line": 98, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, msg, opts", - "arity": 4, - "function": "transport_dispatch", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "publish/4", - "line": 89, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "base64", - "arity": 1, - "function": "safe_decode64!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "new_session/4", - "line": 156, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_status(conn, :gone), token, []", - "arity": 3, - "function": "status_token_messages_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "new_session/4", - "line": 155, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, data, opts", - "arity": 3, - "function": "sign_token", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "new_session/4", - "line": 151, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_status(conn, :forbidden)", - "arity": 1, - "function": "status_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "new_session/4", - "line": 144, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "conn, endpoint, keys, Keyword.take(opts, [:check_csrf])", - "arity": 4, - "function": "connect_info", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "new_session/4", - "line": 141, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, opts[:auth_token]", - "arity": 2, - "function": "maybe_auth_token_from_header", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 188, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_status(conn, status), conn.params()[\"token\"], messages", - "arity": 3, - "function": "status_token_messages_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 182, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:expired, client_ref, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 177, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:expired, client_ref, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 171, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:flush, client_ref, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 163, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint, server_ref, {:flush, client_ref, ref}", - "arity": 3, - "function": "broadcast_from!", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "listen/4", - "line": 162, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "server_ref", - "arity": 1, - "function": "client_ref", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 58, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, endpoint, handler, opts", - "arity": 4, - "function": "new_session", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 55, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "new_conn, server_ref, endpoint, opts", - "arity": 4, - "function": "listen", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 53, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, conn.params(), endpoint, opts", - "arity": 4, - "function": "resume_session", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 69, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_status(conn, :gone)", - "arity": 1, - "function": "status_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 66, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "new_conn, server_ref, endpoint, opts", - "arity": 4, - "function": "publish", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "dispatch/4", - "line": 64, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, conn.params(), endpoint, opts", - "arity": 4, - "function": "resume_session", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "call/2", - "line": 31, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "status_json", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "call/2", - "line": 29, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Plug.Conn.put_resp_header(Plug.Conn.fetch_query_params(conn), \"access-control-allow-origin\", \"*\"), endpoint, opts", - "arity": 3, - "function": "code_reload", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 30, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n), opts[:transport_log]", - "arity": 2, - "function": "transport_log", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 31, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n ),\n opts[:transport_log]\n), handler, endpoint, opts, &status_json/1", - "arity": 5, - "function": "check_origin", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "call/2", - "line": 32, - "module": "Phoenix.Transports.LongPoll", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Transport.check_origin(\n Phoenix.Socket.Transport.transport_log(\n Phoenix.Socket.Transport.code_reload(\n Plug.Conn.put_resp_header(\n Plug.Conn.fetch_query_params(conn),\n \"access-control-allow-origin\",\n \"*\"\n ),\n endpoint,\n opts\n ),\n opts[:transport_log]\n ),\n handler,\n endpoint,\n opts,\n &status_json/1\n), endpoint, handler, opts", - "arity": 4, - "function": "dispatch", - "module": "Phoenix.Transports.LongPoll" - } - }, - { - "caller": { - "function": "phoenix_socket_connected/4", - "line": 363, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "filter_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_socket_connected/4", - "line": 357, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "duration", - "arity": 1, - "function": "duration", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_socket_connected/4", - "line": 354, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "result", - "arity": 1, - "function": "connect_result", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_router_dispatch_start/4", - "line": 324, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn.params()", - "arity": 1, - "function": "params", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_router_dispatch_start/4", - "line": 315, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "plug, plug_opts, 2", - "arity": 3, - "function": "mfa", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_router_dispatch_start/4", - "line": 314, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "mod, fun, arity", - "arity": 3, - "function": "mfa", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_router_dispatch_start/4", - "line": 304, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "level, conn", - "arity": 2, - "function": "log_level", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_error_rendered/4", - "line": 284, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "status", - "arity": 1, - "function": "status_to_string", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_error_rendered/4", - "line": 282, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "kind, reason", - "arity": 2, - "function": "error_banner", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_endpoint_stop/4", - "line": 263, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "duration", - "arity": 1, - "function": "duration", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_endpoint_stop/4", - "line": 263, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state", - "arity": 1, - "function": "connection_type", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_endpoint_stop/4", - "line": 262, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "status", - "arity": 1, - "function": "status_to_string", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_endpoint_stop/4", - "line": 255, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "metadata[:options][:log], conn", - "arity": 2, - "function": "log_level", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_endpoint_start/4", - "line": 241, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "metadata[:options][:log], conn", - "arity": 2, - "function": "log_level", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_joined/4", - "line": 405, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "filter_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_joined/4", - "line": 403, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "duration", - "arity": 1, - "function": "duration", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_joined/4", - "line": 400, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "result", - "arity": 1, - "function": "join_result", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_joined/4", - "line": 396, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":log_join, socket, fn ->\n %{result: result, params: params} = metadata\n\n [\n join_result(result),\n socket.topic(),\n \" in \",\n duration(duration),\n \"\\n Parameters: \",\n Kernel.inspect(filter_values(params))\n ]\nend", - "arity": 3, - "function": "channel_log", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_handled_in/4", - "line": 430, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "filter_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_handled_in/4", - "line": 428, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "duration", - "arity": 1, - "function": "duration", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "phoenix_channel_handled_in/4", - "line": 417, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":log_handle_in, socket, fn ->\n %{event: event, params: params} = metadata\n\n [\n \"HANDLED \",\n event,\n \" INCOMING ON \",\n socket.topic(),\n \" (\",\n Kernel.inspect(socket.channel()),\n \") in \",\n duration(duration),\n \"\\n Parameters: \",\n Kernel.inspect(filter_values(params))\n ]\nend", - "arity": 3, - "function": "channel_log", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "params/1", - "line": 336, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "filter_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "keep_values/2", - "line": 219, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "v, match", - "arity": 2, - "function": "keep_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "keep_values/2", - "line": 225, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, match", - "arity": 2, - "function": "keep_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 144, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_channel_handled_in", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 143, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_channel_joined", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 142, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_socket_drain", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 141, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_socket_connected", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 140, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_error_rendered", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 139, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_router_dispatch_start", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 138, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_endpoint_stop", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "install/0", - "line": 137, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 4, - "function": "phoenix_endpoint_start", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "filter_values/2", - "line": 183, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "values, match", - "arity": 2, - "function": "keep_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "filter_values/2", - "line": 182, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "values, key_match, value_match", - "arity": 3, - "function": "discard_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "filter_values/2", - "line": 181, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "filter", - "arity": 1, - "function": "compile_filter", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "discard_values/3", - "line": 201, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "v, key_match, value_match", - "arity": 3, - "function": "discard_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "discard_values/3", - "line": 207, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, key_match, value_match", - "arity": 3, - "function": "discard_values", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "compile_filter/1", - "line": 165, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "compile_discard", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "compile_filter/1", - "line": 167, - "module": "Phoenix.Logger", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "compile_discard", - "module": "Phoenix.Logger" - } - }, - { - "caller": { - "function": "web_app_name/1", - "line": 257, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Kernel.inspect(context.web_module())", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "validate_required_dependencies!/0", - "line": 275, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "generated_with_no_assets_or_esbuild?", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "validate_required_dependencies!/0", - "line": 272, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "\"mix phx.gen.auth requires phoenix_html\", :phx_generator_args", - "arity": 2, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "validate_required_dependencies!/0", - "line": 271, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "generated_with_no_html?", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "validate_required_dependencies!/0", - "line": 268, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "\"mix phx.gen.auth requires ecto_sql\", :phx_generator_args", - "arity": 2, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "validate_args!/1", - "line": 263, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "\"Invalid arguments\"", - "arity": 1, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 1034, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "ss", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 1034, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "mm", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 1034, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "hh", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 1034, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "d", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "timestamp/0", - "line": 1034, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "m", - "arity": 1, - "function": "pad", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "scope_config/3", - "line": 348, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, key, default_scope, assign_key", - "arity": 4, - "function": "scope_config_string", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "scope_config/3", - "line": 347, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, key, default_scope, assign_key", - "arity": 4, - "function": "new_scope", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "scope_config/3", - "line": 341, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, existing_scopes", - "arity": 2, - "function": "find_scope_name", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "scope_config/3", - "line": 336, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context.context_app()", - "arity": 1, - "function": "scopes_from_config", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "run/2", - "line": 240, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, binding, paths", - "arity": 3, - "function": "copy_new_files", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 241, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "copy_new_files(context, binding, paths), paths, binding", - "arity": 3, - "function": "inject_conn_case_helpers", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 242, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding), hashing_library", - "arity": 2, - "function": "inject_hashing_config", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 243, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n), binding", - "arity": 2, - "function": "maybe_inject_scope_config", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 244, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n), hashing_library", - "arity": 2, - "function": "maybe_inject_mix_dependency", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 245, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n), paths, binding", - "arity": 3, - "function": "inject_routes", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 246, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n), binding", - "arity": 2, - "function": "maybe_inject_router_import", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 247, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n), binding", - "arity": 2, - "function": "maybe_inject_router_plug", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 248, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n), binding", - "arity": 2, - "function": "maybe_inject_app_layout_menu", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 249, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n), paths, binding", - "arity": 3, - "function": "maybe_inject_agents_md", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 250, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "maybe_inject_agents_md(\n maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(copy_new_files(context, binding, paths), paths, binding),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n ),\n paths,\n binding\n)", - "arity": 1, - "function": "maybe_print_mailer_installation_instructions", - "module": "Mix.Tasks.Phx.Gen.Notifier" - } - }, - { - "caller": { - "function": "run/2", - "line": 251, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Notifier.maybe_print_mailer_installation_instructions(\n maybe_inject_agents_md(\n maybe_inject_app_layout_menu(\n maybe_inject_router_plug(\n maybe_inject_router_import(\n inject_routes(\n maybe_inject_mix_dependency(\n maybe_inject_scope_config(\n inject_hashing_config(\n inject_conn_case_helpers(\n copy_new_files(context, binding, paths),\n paths,\n binding\n ),\n hashing_library\n ),\n binding\n ),\n hashing_library\n ),\n paths,\n binding\n ),\n binding\n ),\n binding\n ),\n binding\n ),\n paths,\n binding\n )\n)", - "arity": 1, - "function": "print_shell_instructions", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 237, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 235, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "generator_paths", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "run/2", - "line": 231, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context, opts[:scope], Keyword.get(opts, :assign_key, \"current_scope\")", - "arity": 3, - "function": "scope_config", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 229, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "datetime_now", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 228, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "datetime_module", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 226, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ecto_adapter", - "arity": 1, - "function": "test_case_options", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 225, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "web_path_prefix", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 224, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "router_scope", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 219, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "web_app_name", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 212, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ecto_adapter", - "arity": 1, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Auth.Migration" - } - }, - { - "caller": { - "function": "run/2", - "line": 209, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "schema", - "arity": 1, - "function": "get_ecto_adapter!", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 202, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "validate_required_dependencies!", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 196, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "context", - "arity": 1, - "function": "prompt_for_code_injection", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/2", - "line": 195, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "put_live_option", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 193, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": ":erlang.++(context_args, [\"--no-scope\"]), [help_module: Mix.Tasks.Phx.Gen.Auth]", - "arity": 2, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "run/2", - "line": 185, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "build_hashing_library!", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 184, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "parsed", - "arity": 1, - "function": "validate_args!", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "run/2", - "line": 181, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "Mix.Tasks.Phx.Gen.Auth", - "arity": 1, - "function": "ensure_live_view_compat!", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "raise_with_help/1", - "line": 1068, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "msg, :general", - "arity": 2, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 432, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 433, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "files_to_be_generated(binding)", - "arity": 1, - "function": "prompt_for_conflicts", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "prompt_for_conflicts/1", - "line": 429, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "prompt_for_scope_conflicts", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "print_unable_to_read_file_error/2", - "line": 1062, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "<<\"\\nUnable to read file \"::binary,\n String.Chars.to_string(Path.relative_to_cwd(file_path))::binary, \".\\n\\n\"::binary,\n String.Chars.to_string(help_text)::binary, \"\\n\"::binary>>, 2", - "arity": 2, - "function": "indent_spaces", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "potential_layout_file_paths/1", - "line": 828, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new_scope/4", - "line": 394, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "key, %{\n default:\n case default_scope do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> true\n _ -> false\n end,\n module: Module.concat([context.module(), \"Scope\"]),\n assign_key: :erlang.binary_to_atom(assign_key),\n access_path: [\n :erlang.binary_to_atom(context.schema.singular()),\n case context.schema.opts()[:primary_key] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :id\n x -> x\n end\n ],\n schema_key:\n :erlang.binary_to_atom(\n < :id\n x -> x\n end\n )::binary>>\n ),\n schema_type:\n case context.schema.binary_id() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :id\n _ -> :binary_id\n end,\n schema_table: context.schema.table(),\n test_data_fixture: Module.concat([context.module(), \"Fixtures\"]),\n test_setup_helper:\n :erlang.binary_to_atom(\n <<\"register_and_log_in_\"::binary,\n String.Chars.to_string(context.schema.singular())::binary>>,\n :utf8\n )\n}", - "arity": 2, - "function": "new!", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "maybe_inject_scope_config/2", - "line": 872, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, binding", - "arity": 2, - "function": "inject_scope_config", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 771, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path, help_text", - "arity": 2, - "function": "print_unable_to_read_file_error", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 770, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 757, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path, \" - plug\"", - "arity": 2, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 756, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, binding", - "arity": 2, - "function": "router_plug_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 755, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "read_file", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 753, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file_path, binding", - "arity": 2, - "function": "router_plug_help_text", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_router_plug/2", - "line": 751, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 744, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path, help_text", - "arity": 2, - "function": "print_unable_to_read_file_error", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 743, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 730, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path, \" - imports\"", - "arity": 2, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 725, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, inject, fn capture, capture ->\n String.replace(\n capture,\n use_line,\n <>\n )\nend", - "arity": 3, - "function": "inject_unless_contains", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 723, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "read_file", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_router_import/2", - "line": 704, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "maybe_inject_mix_dependency/2", - "line": 680, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_mix_dependency/2", - "line": 678, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, mix_dependency", - "arity": 2, - "function": "mix_dependency_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_mix_dependency/2", - "line": 674, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app, \"mix.exs\"", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 790, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file_path, binding", - "arity": 2, - "function": "app_layout_menu_help_text", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 781, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 779, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "binding, File.read!(file_path)", - "arity": 2, - "function": "app_layout_menu_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 798, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "potential_layout_file_paths", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 794, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "binding", - "arity": 1, - "function": "app_layout_menu_code_to_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "maybe_inject_app_layout_menu/2", - "line": 778, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "get_layout_html_path", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_agents_md/3", - "line": 937, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "maybe_inject_agents_md/3", - "line": 927, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "File.cwd!()", - "arity": 1, - "function": "in_umbrella?", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "maybe_inject_agents_md/3", - "line": 922, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/AGENTS.md\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 632, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 633, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding)", - "arity": 1, - "function": "prepend_newline", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 634, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/test_cases.exs\", binding)\n), test_file", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_tests/3", - "line": 629, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_test_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_scope_config/2", - "line": 897, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_scope_config/2", - "line": 895, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, scope_config", - "arity": 2, - "function": "config_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_scope_config/2", - "line": 890, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "read_file", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_scope_config/2", - "line": 882, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "File.cwd!()", - "arity": 1, - "function": "in_umbrella?", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_routes/3", - "line": 665, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/routes.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_routes/3", - "line": 666, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/routes.ex\", binding), file_path", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_routes/3", - "line": 661, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_hashing_config/2", - "line": 859, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file_path, hashing_library", - "arity": 2, - "function": "test_config_help_text", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_hashing_config/2", - "line": 852, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_hashing_config/2", - "line": 850, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, hashing_library", - "arity": 2, - "function": "test_config_inject", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_hashing_config/2", - "line": 845, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "read_file", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_hashing_config/2", - "line": 837, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "File.cwd!()", - "arity": 1, - "function": "in_umbrella?", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_context_test_fixtures/3", - "line": 645, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_context_test_fixtures/3", - "line": 646, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\", binding)", - "arity": 1, - "function": "prepend_newline", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_context_test_fixtures/3", - "line": 647, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "prepend_newline(\n Mix.Phoenix.eval_from(\n paths,\n \"priv/templates/phx.gen.auth/context_fixtures_functions.ex\",\n binding\n )\n), test_fixtures_file", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_context_test_fixtures/3", - "line": 642, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_test_fixtures_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_context_functions/3", - "line": 623, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_context_functions/3", - "line": 624, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding)", - "arity": 1, - "function": "prepend_newline", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_context_functions/3", - "line": 625, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "prepend_newline(\n Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/context_functions.ex\", binding)\n), file", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_context_functions/3", - "line": 620, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "ensure_context_file_exists", - "module": "Mix.Tasks.Phx.Gen.Context" - } - }, - { - "caller": { - "function": "inject_conn_case_helpers/3", - "line": 654, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth/conn_case.exs\", binding", - "arity": 3, - "function": "eval_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "inject_conn_case_helpers/3", - "line": 655, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.eval_from(paths, \"priv/templates/phx.gen.auth/conn_case.exs\", binding), test_file", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 1010, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "content_to_inject, 2", - "arity": 2, - "function": "indent_spaces", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 1003, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path, <<\"\\nPlease add the following to the end of your equivalent\\n\"::binary,\n String.Chars.to_string(Path.relative_to_cwd(file_path))::binary, \" module:\\n\\n\"::binary,\n String.Chars.to_string(indent_spaces(content_to_inject, 2))::binary, \"\\n\"::binary>>", - "arity": 2, - "function": "print_unable_to_read_file_error", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 1001, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 994, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "print_injecting", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 993, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "file, content_to_inject", - "arity": 2, - "function": "inject_before_final_end", - "module": "Mix.Tasks.Phx.Gen.Auth.Injector" - } - }, - { - "caller": { - "function": "inject_before_final_end/2", - "line": 992, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "file_path", - "arity": 1, - "function": "read_file", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "get_layout_html_path/1", - "line": 823, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context", - "arity": 1, - "function": "potential_layout_file_paths", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "find_scope_name/2", - "line": 371, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "existing_scopes, <>", - "arity": 2, - "function": "is_new_scope?", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "find_scope_name/2", - "line": 367, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "existing_scopes, <>", - "arity": 2, - "function": "is_new_scope?", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "find_scope_name/2", - "line": 363, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "existing_scopes, context.schema.singular()", - "arity": 2, - "function": "is_new_scope?", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 601, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":erlang.++(default_files, non_live_files)", - "arity": 1, - "function": "remap_files", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 562, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": ":erlang.++(default_files, live_files)", - "arity": 1, - "function": "remap_files", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 493, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "timestamp", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 487, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context_app, \"priv/repo/migrations\"", - "arity": 2, - "function": "context_app_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 486, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_test_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "files_to_be_generated/1", - "line": 485, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "context_app", - "arity": 1, - "function": "web_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 614, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_context_test_fixtures", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 613, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_tests", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 612, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "context, paths, binding", - "arity": 3, - "function": "inject_context_functions", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 611, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "paths, \"priv/templates/phx.gen.auth\", binding, files", - "arity": 4, - "function": "copy_from", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "copy_new_files/3", - "line": 610, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "binding", - "arity": 1, - "function": "files_to_be_generated", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "build_hashing_library!/1", - "line": 321, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "<<\"Unknown value for --hashing-lib \"::binary, Kernel.inspect(unknown_library)::binary>>, :hashing_lib", - "arity": 2, - "function": "raise_with_help", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "build_hashing_library!/1", - "line": 314, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "default_hashing_library_option", - "module": "Mix.Tasks.Phx.Gen.Auth" - } - }, - { - "caller": { - "function": "build_hashing_library!/1", - "line": 315, - "module": "Mix.Tasks.Phx.Gen.Auth", - "file": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "Keyword.get_lazy(opts, :hashing_lib, &default_hashing_library_option/0)", - "arity": 1, - "function": "build", - "module": "Mix.Tasks.Phx.Gen.Auth.HashingLibrary" - } - }, - { - "caller": { - "function": "origin_allowed?/4", - "line": 623, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint.config(:url)[:host]", - "arity": 1, - "function": "host_to_binary", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "origin_allowed?/4", - "line": 623, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "uri.host(), host_to_binary(endpoint.config(:url)[:host])", - "arity": 2, - "function": "compare?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "origin_allowed?/4", - "line": 626, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "uri, check_origin", - "arity": 2, - "function": "origin_allowed?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "origin_allowed?/2", - "line": 634, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "origin_host, allowed_host", - "arity": 2, - "function": "compare_host?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "origin_allowed?/2", - "line": 633, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "origin_port, allowed_port", - "arity": 2, - "function": "compare?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "origin_allowed?/2", - "line": 632, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "origin_scheme, allowed_scheme", - "arity": 2, - "function": "compare?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "load_config/2", - "line": 256, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Keyword.merge(module.default_config(), config)", - "arity": 1, - "function": "load_config", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "load_config/1", - "line": 276, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "session", - "arity": 1, - "function": "init_session", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "host_to_binary/1", - "line": 652, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "System.get_env(env_var)", - "arity": 1, - "function": "host_to_binary", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "fetch_uri/1", - "line": 548, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "URI, %{\n fragment: nil,\n userinfo: nil,\n scheme: String.Chars.to_string(conn.scheme()),\n query: conn.query_string(),\n port: conn.port(),\n host: conn.host(),\n authority: conn.host(),\n path: conn.request_path()\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_session/4", - "line": 517, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, session, csrf_token_key", - "arity": 3, - "function": "csrf_token_valid?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_session/4", - "line": 527, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "session_config", - "arity": 1, - "function": "init_session", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_session/4", - "line": 527, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, endpoint, init_session(session_config), opts", - "arity": 4, - "function": "connect_session", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 499, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, endpoint, session, opts", - "arity": 4, - "function": "connect_session", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 496, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, \"sec-websocket-\"", - "arity": 2, - "function": "fetch_headers", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 493, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "fetch_user_agent", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 490, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "fetch_uri", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 487, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, \"x-\"", - "arity": 2, - "function": "fetch_headers", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "connect_info/4", - "line": 484, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "fetch_trace_context_headers", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "code_reload/3", - "line": 309, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "endpoint", - "arity": 1, - "function": "reload", - "module": "Phoenix.CodeReloader" - } - }, - { - "caller": { - "function": "check_subprotocols/2", - "line": 416, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, subprotocols", - "arity": 2, - "function": "subprotocols_error_response", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "check_subprotocols/2", - "line": 421, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, subprotocols", - "arity": 2, - "function": "subprotocols_error_response", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "check_origin_config/3", - "line": 577, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "parse_origin", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "check_origin_config/3", - "line": 573, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "endpoint, {:check_origin, handler}, fn _ ->\n check_origin =\n case Keyword.get(opts, :check_origin, endpoint.config(:check_origin)) do\n origins when :erlang.is_list(origins) ->\n Enum.map(origins, &parse_origin/1)\n\n boolean when :erlang.is_boolean(boolean) ->\n boolean\n\n {module, function, arguments} ->\n {module, function, arguments}\n\n :conn ->\n :conn\n\n invalid ->\n :erlang.error(\n ArgumentError.exception(\n <<\":check_origin expects a boolean, list of hosts, :conn, or MFA tuple, got: \"::binary,\n Kernel.inspect(invalid)::binary>>\n )\n )\n end\n\n {:cache, check_origin}\nend", - "arity": 3, - "function": "cache", - "module": "Phoenix.Config" - } - }, - { - "caller": { - "function": "check_origin/5", - "line": 352, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "check_origin, URI.parse(origin), endpoint, conn", - "arity": 4, - "function": "origin_allowed?", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "check_origin/5", - "line": 346, - "module": "Phoenix.Socket.Transport", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "handler, endpoint, opts", - "arity": 3, - "function": "check_origin_config", - "module": "Phoenix.Socket.Transport" - } - }, - { - "caller": { - "function": "value/3", - "line": 287, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Keyword.fetch!(schema.types(), field), value", - "arity": 2, - "function": "inspect_value", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "types/1", - "line": 513, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "val", - "arity": 1, - "function": "schema_type", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "types/1", - "line": 512, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "val", - "arity": 1, - "function": "schema_type", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "types/1", - "line": 511, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "vals", - "arity": 1, - "function": "translate_enum_vals", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 360, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_naive_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 357, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_naive_datetime", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 350, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 342, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_datetime", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 335, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Time, %{calendar: Calendar.ISO, hour: 14, minute: 0, second: 0, microsecond: {0, 6}}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 332, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Time, %{calendar: Calendar.ISO, hour: 14, minute: 0, second: 0, microsecond: {0, 0}}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 308, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "values, :create", - "arity": 2, - "function": "build_enum_values", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 305, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "type, :create", - "arity": 2, - "function": "build_array_values", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 384, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_naive_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 383, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_naive_datetime", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 382, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 381, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_datetime", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 379, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Time, %{calendar: Calendar.ISO, hour: 15, minute: 1, second: 1, microsecond: {0, 6}}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 378, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Time, %{calendar: Calendar.ISO, hour: 15, minute: 1, second: 1, microsecond: {0, 0}}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 370, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "values, :update", - "arity": 2, - "function": "build_enum_values", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "type_to_default/3", - "line": 369, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "type, :update", - "arity": 2, - "function": "build_array_values", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "split_flags/5", - "line": 186, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, name, attrs, [name | uniques], redacts", - "arity": 5, - "function": "split_flags", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "split_flags/5", - "line": 189, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, name, attrs, uniques, [name | redacts]", - "arity": 5, - "function": "split_flags", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "partition_attrs_and_assocs/3", - "line": 477, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "key", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "partition_attrs_and_assocs/3", - "line": 473, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "scope, key_id", - "arity": 2, - "function": "validate_scope_and_reference_conflict!", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "params/2", - "line": 210, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "k, t, action", - "arity": 3, - "function": "type_to_default", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 158, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs, fixture_unique_functions", - "arity": 2, - "function": "fixture_params", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 156, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "migration_module", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 153, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "sample_id", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 151, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "web_path, schema_plural", - "arity": 2, - "function": "route_prefix", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 150, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "web_path, singular", - "arity": 2, - "function": "route_helper", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 145, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs, :update", - "arity": 2, - "function": "params", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 141, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs", - "arity": 1, - "function": "migration_defaults", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 138, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema_plural", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 137, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "singular", - "arity": 1, - "function": "humanize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 136, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "table, assocs, uniques", - "arity": 3, - "function": "indexes", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 133, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs", - "arity": 1, - "function": "schema_defaults", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 116, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Mix.Phoenix.Schema, %{\n opts: opts,\n migration?: Keyword.get(opts, :migration, true),\n module: module,\n repo: repo,\n repo_alias: repo_alias,\n table: table,\n embedded?: embedded?,\n alias: Module.concat(List.last(Module.split(module)), nil),\n file: file,\n attrs: attrs,\n plural: schema_plural,\n singular: singular,\n collection: collection,\n optionals: optionals,\n assocs: assocs,\n types: types,\n defaults: schema_defaults(attrs),\n uniques: uniques,\n redacts: redacts,\n indexes: indexes(table, assocs, uniques),\n human_singular: Phoenix.Naming.humanize(singular),\n human_plural: Phoenix.Naming.humanize(schema_plural),\n binary_id: opts[:binary_id],\n timestamp_type:\n case opts[:timestamp_type] do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> :naive_datetime\n x -> x\n end,\n migration_defaults: migration_defaults(attrs),\n string_attr: string_attr,\n params: %{\n create: create_params,\n update: params(attrs, :update),\n default_key:\n case string_attr do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n default_params_key\n\n x ->\n x\n end\n },\n web_namespace: web_namespace,\n web_path: web_path,\n route_helper: route_helper(web_path, singular),\n route_prefix: route_prefix(web_path, schema_plural),\n api_route_prefix: api_prefix,\n sample_id: sample_id(opts),\n context_app: ctx_app,\n generate?: generate?,\n migration_module: migration_module(),\n fixture_unique_functions: Enum.sort(fixture_unique_functions),\n fixture_params: fixture_params(attrs, fixture_unique_functions),\n prefix: opts[:prefix],\n scope: scope\n}", - "arity": 2, - "function": "%", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 114, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "singular, uniques, attrs", - "arity": 3, - "function": "fixture_unique_functions", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 104, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs, :create", - "arity": 2, - "function": "params", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 103, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "types", - "arity": 1, - "function": "string_attr", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 100, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "List.last(Module.split(module))", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 91, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "web_namespace", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 90, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "opts[:web]", - "arity": 1, - "function": "camelize", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 89, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "attrs", - "arity": 1, - "function": "types", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 88, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "cli_attrs", - "arity": 1, - "function": "attrs", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 88, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "module, attrs(cli_attrs), scope", - "arity": 3, - "function": "partition_attrs_and_assocs", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 87, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "cli_attrs", - "arity": 1, - "function": "extract_attr_flags", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "new/4", - "line": 86, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, opts[:scope], opts[:no_scope]", - "arity": 3, - "function": "scope_from_opts", - "module": "Mix.Phoenix.Scope" - } - }, - { - "caller": { - "function": "new/4", - "line": 84, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app, <>", - "arity": 2, - "function": "context_lib_path", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/4", - "line": 80, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "schema_name", - "arity": 1, - "function": "underscore", - "module": "Phoenix.Naming" - } - }, - { - "caller": { - "function": "new/4", - "line": 79, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "ctx_app", - "arity": 1, - "function": "context_base", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/4", - "line": 77, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "otp_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "new/4", - "line": 76, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "context_app", - "module": "Mix.Phoenix" - } - }, - { - "caller": { - "function": "format_fields_for_schema/1", - "line": 261, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Enum.member?(schema.redacts(), k)", - "arity": 1, - "function": "maybe_redact_field", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "format_fields_for_schema/1", - "line": 261, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "v", - "arity": 1, - "function": "type_and_opts_for_schema", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "fixture_params/2", - "line": 628, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "attr, type, :create", - "arity": 3, - "function": "type_to_default", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "extract_attr_flags/1", - "line": 179, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Enum.reverse(rest), attr_name, attrs, uniques, redacts", - "arity": 5, - "function": "split_flags", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "build_utc_naive_datetime/0", - "line": 422, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_naive_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "build_utc_datetime/0", - "line": 416, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_utc_datetime_usec", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "build_enum_values/2", - "line": 405, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "values", - "arity": 1, - "function": "translate_enum_vals", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "attrs/1", - "line": 201, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "String.split(attr, \":\", parts: 3)", - "arity": 1, - "function": "list_to_attr", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "attrs/1", - "line": 202, - "module": "Mix.Phoenix.Schema", - "file": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "list_to_attr(String.split(attr, \":\", parts: 3))", - "arity": 1, - "function": "validate_attr!", - "module": "Mix.Phoenix.Schema" - } - }, - { - "caller": { - "function": "text_response/2", - "line": 403, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :text", - "arity": 2, - "function": "response_content_type", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "text_response/2", - "line": 402, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, status", - "arity": 2, - "function": "response", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "response_content_type?/2", - "line": 327, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "header", - "arity": 1, - "function": "parse_content_type", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "response_content_type/2", - "line": 316, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "h, format", - "arity": 2, - "function": "response_content_type?", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "redirected_to/2", - "line": 445, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, Plug.Conn.Status.code(status)", - "arity": 2, - "function": "redirected_to", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 597, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "[conn: conn, router: router]", - "arity": 1, - "function": "exception", - "module": "Phoenix.Router.NoRouteError" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 595, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router, \"GET\", path, case host do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> conn.host()\n x -> x\nend", - "arity": 4, - "function": "route_info", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 593, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, router, path", - "arity": 3, - "function": "remove_script_name", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 592, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, status", - "arity": 2, - "function": "redirected_to", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 592, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "URI, %{path: path, host: host}", - "arity": 2, - "function": "%", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "redirected_params/2", - "line": 591, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "router_module", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "recycle/2", - "line": 477, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "build_conn", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "recycle/2", - "line": 482, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Test.put_peer_data(\n Plug.Test.recycle_cookies(\n :maps.put(:remote_ip, conn.remote_ip(), :maps.put(:host, conn.host(), build_conn())),\n conn\n ),\n Plug.Conn.get_peer_data(conn)\n), conn.req_headers(), headers", - "arity": 3, - "function": "copy_headers", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "put_flash/3", - "line": 293, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn, key, value", - "arity": 3, - "function": "put_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "path_params/2", - "line": 634, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "[conn: conn, router: router]", - "arity": 1, - "function": "exception", - "module": "Phoenix.Router.NoRouteError" - } - }, - { - "caller": { - "function": "path_params/2", - "line": 629, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router, \"GET\", to, conn.host()", - "arity": 4, - "function": "route_info", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "path_params/2", - "line": 627, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "router_module", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "json_response/2", - "line": 422, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "json_response/2", - "line": 420, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :json", - "arity": 2, - "function": "response_content_type", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "json_response/2", - "line": 419, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, status", - "arity": 2, - "function": "response", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "html_response/2", - "line": 388, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :html", - "arity": 2, - "function": "response_content_type", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "html_response/2", - "line": 387, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, status", - "arity": 2, - "function": "response", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "get_flash/2", - "line": 286, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn.assigns.flash(), key", - "arity": 2, - "function": "get", - "module": "Phoenix.Flash" - } - }, - { - "caller": { - "function": "fetch_flash/1", - "line": 271, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "fetch_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "ensure_recycled/1", - "line": 500, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "recycle", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "dispatch/5", - "line": 224, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "ensure_recycled", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "dispatch/5", - "line": 225, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "ensure_recycled(conn), endpoint, method, path_or_action, params_or_body", - "arity": 5, - "function": "dispatch_endpoint", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "dispatch/5", - "line": 227, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_private(\n dispatch_endpoint(ensure_recycled(conn), endpoint, method, path_or_action, params_or_body),\n :phoenix_recycled,\n false\n)", - "arity": 1, - "function": "from_set_to_sent", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "discard_previously_sent/0", - "line": 720, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "discard_previously_sent", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "discard_previously_sent/0", - "line": 719, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "discard_previously_sent", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "clear_flash/1", - "line": 299, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn", - "arity": 1, - "function": "clear_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "build_conn/3", - "line": 152, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Conn, %{\n adapter: {Plug.MissingAdapter, nil},\n assigns: %{},\n body_params: %{__struct__: Plug.Conn.Unfetched, aspect: :body_params},\n cookies: %{__struct__: Plug.Conn.Unfetched, aspect: :cookies},\n halted: false,\n host: \"www.example.com\",\n method: \"GET\",\n owner: nil,\n params: %{__struct__: Plug.Conn.Unfetched, aspect: :params},\n path_info: [],\n path_params: %{},\n port: 0,\n private: %{},\n query_params: %{__struct__: Plug.Conn.Unfetched, aspect: :query_params},\n query_string: \"\",\n remote_ip: nil,\n req_cookies: %{__struct__: Plug.Conn.Unfetched, aspect: :cookies},\n req_headers: [],\n request_path: \"\",\n resp_body: nil,\n resp_cookies: %{},\n resp_headers: [{\"cache-control\", \"max-age=0, private, must-revalidate\"}],\n scheme: :http,\n script_name: [],\n secret_key_base: nil,\n state: :unset,\n status: nil\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "build_conn/0", - "line": 140, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": ":get, \"/\", nil", - "arity": 3, - "function": "build_conn", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "assert_error_sent/2", - "line": 685, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "discard_previously_sent", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "assert_error_sent/2", - "line": 682, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "func", - "arity": 1, - "function": "wrap_request", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "assert_error_sent/2", - "line": 683, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "wrap_request(func), expected_status", - "arity": 2, - "function": "receive_response", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "assert_error_sent/2", - "line": 679, - "module": "Phoenix.ConnTest", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "discard_previously_sent", - "module": "Phoenix.ConnTest" - } - }, - { - "caller": { - "function": "user_connect/6", - "line": 653, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "set_label", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "user_connect/6", - "line": 646, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket, %{}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "user_connect/6", - "line": 624, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket, %{\n assigns: %{},\n channel: nil,\n channel_pid: nil,\n id: nil,\n join_ref: nil,\n joined: false,\n private: %{},\n ref: nil,\n topic: nil,\n transport_pid: nil,\n handler: handler,\n endpoint: endpoint,\n pubsub_server: endpoint.config(:pubsub_server),\n serializer: serializer,\n transport: transport\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "socket_close/2", - "line": 873, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, topic, join_ref", - "arity": 3, - "function": "encode_close", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "socket_close/2", - "line": 872, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state, pid, topic, monitor_ref", - "arity": 4, - "function": "delete_channel", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 692, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 685, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{join_ref: nil, ref: ref, topic: \"phoenix\", status: :ok, payload: %{}}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 730, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, message", - "arity": 2, - "function": "encode_ignore", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 725, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 717, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{join_ref: join_ref, ref: ref, topic: topic, status: :error, payload: reply}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 714, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 713, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state, pid, topic, join_ref", - "arity": 4, - "function": "put_channel", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 705, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{join_ref: join_ref, ref: ref, topic: topic, status: :ok, payload: reply}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 703, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "socket, channel, message, opts", - "arity": 4, - "function": "join", - "module": "Phoenix.Channel.Server" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 750, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "nil, message, new_state, new_socket", - "arity": 4, - "function": "handle_in", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 748, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "pid, {state, socket}", - "arity": 2, - "function": "socket_close", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 747, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "pid", - "arity": 1, - "function": "shutdown_duplicate_channel", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 760, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "state, pid, topic, :leaving", - "arity": 4, - "function": "update_channel_status", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 797, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 789, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{ref: ref, join_ref: join_ref, topic: topic, status: :ok, payload: %{}}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "handle_in/4", - "line": 803, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, message", - "arity": 2, - "function": "encode_ignore", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_on_exit/4", - "line": 830, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, message", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_on_exit/4", - "line": 829, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{join_ref: ref, ref: ref, topic: topic, event: \"phx_error\", payload: %{}}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_ignore/2", - "line": 835, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, reply", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_ignore/2", - "line": 834, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Reply, %{join_ref: nil, ref: ref, topic: topic, status: :error, payload: %{reason: \"unmatched topic\"}}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_close/3", - "line": 852, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "socket, message", - "arity": 2, - "function": "encode_reply", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "encode_close/3", - "line": 844, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.Socket.Message, %{join_ref: join_ref, ref: join_ref, topic: topic, event: \"phx_close\", payload: %{}}", - "arity": 2, - "function": "%", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "channel/3", - "line": 402, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "channel/3", - "line": 398, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "module, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "assign/3", - "line": 343, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, [{key, value}]", - "arity": 2, - "function": "assign", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "assign/2", - "line": 368, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, fun.(socket.assigns())", - "arity": 2, - "function": "assign", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__init__/1", - "line": 537, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket", - "arity": 1, - "function": "set_label", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__info__/2", - "line": 551, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "socket, topic, join_ref, reason", - "arity": 4, - "function": "encode_on_exit", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__info__/2", - "line": 550, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "state, pid, topic, ref", - "arity": 4, - "function": "delete_channel", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__info__/2", - "line": 572, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "pid, state", - "arity": 2, - "function": "socket_close", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__in__/2", - "line": 544, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Map.get(state.channels(), topic), message, state, socket", - "arity": 4, - "function": "handle_in", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__connect__/3", - "line": 514, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "result", - "arity": 1, - "function": "result", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__connect__/3", - "line": 504, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "user_socket, endpoint, transport, serializer, params, connect_info", - "arity": 6, - "function": "user_connect", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__connect__/3", - "line": 502, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Keyword.fetch!(options, :serializer), vsn", - "arity": 2, - "function": "negotiate_serializer", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 432, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "topic_pattern", - "arity": 1, - "function": "to_topic_match", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 433, - "module": "Phoenix.Socket", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "to_topic_match(topic_pattern), module, opts", - "arity": 3, - "function": "defchannel", - "module": "Phoenix.Socket" - } - }, - { - "caller": { - "function": "trace/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "trace/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :trace, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scoped_path/2", - "line": 1181, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router_module, path", - "arity": 2, - "function": "full_path", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "scoped_alias/2", - "line": 1173, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "router_module, alias", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router.Scope" - } - }, - { - "caller": { - "function": "scope/4", - "line": 1144, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "options, context", - "arity": 2, - "function": "do_scope", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scope/4", - "line": 1135, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "alias, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scope/3", - "line": 1115, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "options, context", - "arity": 2, - "function": "do_scope", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scope/3", - "line": 1100, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scope/2", - "line": 1078, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "options, context", - "arity": 2, - "function": "do_scope", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "scope/2", - "line": 1073, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "route_info/4", - "line": 1264, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "router, method, split_path, host", - "arity": 4, - "function": "route_info", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "resources/4", - "line": 1000, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "path, controller, opts, [do: nested_context]", - "arity": 4, - "function": "add_resources", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "resources/3", - "line": 1007, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "path, controller, [], [do: nested_context]", - "arity": 4, - "function": "add_resources", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "resources/3", - "line": 1011, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "path, controller, opts, [do: nil]", - "arity": 4, - "function": "add_resources", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "resources/2", - "line": 1018, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "path, controller, [], [do: nil]", - "arity": 4, - "function": "add_resources", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "put/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "put/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :put, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "post/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "post/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :post, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "plug/2", - "line": 829, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, opts, __CALLER__", - "arity": 3, - "function": "expand_plug_and_opts", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "pipe_through/1", - "line": 907, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "pipe_through/1", - "line": 906, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "plug_init_mode", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "patch/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "patch/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :patch, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "options/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "options/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :options, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "match/5", - "line": 710, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "match/5", - "line": 710, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, verb, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "head/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "head/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :head, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "get/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "get/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :get, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "forward/4", - "line": 1221, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":forward, :*, path, plug, plug_opts, router_opts", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "forward/4", - "line": 1217, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, plug_opts, __CALLER__", - "arity": 3, - "function": "expand_plug_and_opts", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "expand_plug_and_opts/3", - "line": 852, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "capture, caller", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "expand_plug_and_opts/3", - "line": 845, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "plug, caller", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "expand_plug_and_opts/3", - "line": 841, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "plug_init_mode", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "delete/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "delete/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :delete, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "connect/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "connect/4", - "line": 734, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": ":match, :connect, path, expand_alias(plug, __CALLER__), plug_opts, options", - "arity": 6, - "function": "add_route", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "build_pipes/2", - "line": 665, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "plug_init_mode", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "build_match_pipes/3", - "line": 630, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "name, pipe_through", - "arity": 2, - "function": "build_pipes", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "build_match/2", - "line": 610, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "route, path_params", - "arity": 2, - "function": "build_metadata", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "build_match/2", - "line": 595, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "route, acc_pipes, known_pipes", - "arity": 3, - "function": "build_match_pipes", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 293, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "verified_routes", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 292, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "match_dispatch", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 291, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 0, - "function": "defs", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 290, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "prelude", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__call__/5", - "line": 414, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Conn, %{}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__call__/5", - "line": 408, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Conn, %{halted: true}", - "arity": 2, - "function": "%", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 508, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, routes_per_path", - "arity": 2, - "function": "build_verify", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 498, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "", - "arity": 2, - "function": "build_match", - "module": "Phoenix.Router" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 494, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "remote", - "callee": { - "args": "env, routes_with_exprs", - "arity": 2, - "function": "define", - "module": "Phoenix.Router.Helpers" - } - }, - { - "caller": { - "function": "__before_compile__/1", - "line": 490, - "module": "Phoenix.Router", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "kind": "defmacro" - }, - "type": "remote", - "callee": { - "args": "capture", - "arity": 1, - "function": "exprs", - "module": "Phoenix.Router.Route" - } - }, - { - "caller": { - "function": "verify_segment/3", - "line": 765, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [\"/\" | acc]", - "arity": 3, - "function": "verify_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_segment/3", - "line": 775, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "dynamic_query, route, [static_query]", - "arity": 3, - "function": "verify_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_segment/3", - "line": 771, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [URI.encode(segment) | acc]", - "arity": 3, - "function": "verify_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_segment/3", - "line": 786, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [static_query_segment]", - "arity": 3, - "function": "verify_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_segment/3", - "line": 804, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [rewrite | acc]", - "arity": 3, - "function": "verify_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_segment/2", - "line": 758, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "segments, route, []", - "arity": 3, - "function": "verify_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_query/3", - "line": 833, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [rewrite | acc]", - "arity": 3, - "function": "verify_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_query/3", - "line": 839, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [\"=\" | acc]", - "arity": 3, - "function": "verify_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_query/3", - "line": 848, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest, route, [param | acc]", - "arity": 3, - "function": "verify_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "verify_query/3", - "line": 852, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "route", - "arity": 1, - "function": "raise_invalid_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/3", - "line": 565, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/3", - "line": 566, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", - "arity": 2, - "function": "inject_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/3", - "line": 569, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "other", - "arity": 1, - "function": "raise_invalid_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/2", - "line": 546, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/2", - "line": 547, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", - "arity": 2, - "function": "inject_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/2", - "line": 543, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :router", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/2", - "line": 550, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "other", - "arity": 1, - "function": "raise_invalid_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/1", - "line": 528, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, sigil_p, __CALLER__, endpoint, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/1", - "line": 529, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, sigil_p, __CALLER__, endpoint, router), __CALLER__", - "arity": 2, - "function": "inject_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/1", - "line": 525, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :router", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/1", - "line": 524, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :endpoint", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "url/1", - "line": 532, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "other", - "arity": 1, - "function": "raise_invalid_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_url/3", - "line": 623, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn_or_socket_or_endpoint_or_uri, path, params", - "arity": 3, - "function": "guarded_unverified_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 714, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "path, conn.script_name()", - "arity": 2, - "function": "path_with_script", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 713, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, router, path", - "arity": 3, - "function": "build_conn_forward_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 712, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, router, path", - "arity": 3, - "function": "build_own_forward_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 715, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "case (case build_own_forward_path(conn, router, path) do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n build_conn_forward_path(conn, router, path)\n\n x ->\n x\n end) do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) ->\n path_with_script(path, conn.script_name())\n\n x ->\n x\nend, params", - "arity": 2, - "function": "append_params", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 719, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "< \"\"\n x -> x\n end::binary, path::binary>>, params", - "arity": 2, - "function": "append_params", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 723, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, router, path, params", - "arity": 4, - "function": "unverified_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "unverified_path/4", - "line": 727, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint.path(path), params", - "arity": 2, - "function": "append_params", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "to_param/1", - "line": 912, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "data", - "arity": 1, - "function": "to_param", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "static_url/2", - "line": 592, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, path", - "arity": 2, - "function": "static_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "static_url/2", - "line": 591, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "static_url, path", - "arity": 2, - "function": "concat_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "static_url/2", - "line": 597, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, path", - "arity": 2, - "function": "static_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "static_path/2", - "line": 690, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, path", - "arity": 2, - "function": "static_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "static_integrity/2", - "line": 879, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, path", - "arity": 2, - "function": "static_integrity", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "static_integrity/2", - "line": 883, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "endpoint, path", - "arity": 2, - "function": "static_integrity", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "sigil_p/2", - "line": 367, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, route, __CALLER__, endpoint, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "sigil_p/2", - "line": 368, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, route, __CALLER__, endpoint, router), __CALLER__", - "arity": 2, - "function": "inject_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "sigil_p/2", - "line": 364, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :router", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "sigil_p/2", - "line": 363, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :endpoint", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "sigil_p/2", - "line": 362, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "extra", - "arity": 1, - "function": "validate_sigil_p!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 983, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "test_path, config.statics()", - "arity": 2, - "function": "static_path?", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 982, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path_rewrite", - "arity": 1, - "function": "materialize_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 963, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "config.path_prefixes(), meta", - "arity": 2, - "function": "compile_prefixes", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 960, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Enum.slice(path_rewrite, 0, 1)", - "arity": 1, - "function": "materialize_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 960, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "materialize_path(Enum.slice(path_rewrite, 0, 1)), config.statics()", - "arity": 2, - "function": "static_path?", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "rewrite_path/4", - "line": 956, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "segments, route", - "arity": 2, - "function": "verify_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/3", - "line": 441, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/3", - "line": 442, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", - "arity": 2, - "function": "inject_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/3", - "line": 438, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "extra", - "arity": 1, - "function": "validate_sigil_p!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/3", - "line": 445, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "other", - "arity": 1, - "function": "raise_invalid_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/2", - "line": 476, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router", - "arity": 5, - "function": "build_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/2", - "line": 477, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "build_route(route, sigil_p, __CALLER__, conn_or_socket_or_endpoint_or_uri, router), __CALLER__", - "arity": 2, - "function": "inject_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/2", - "line": 473, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "__CALLER__, :router", - "arity": 2, - "function": "attr!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/2", - "line": 472, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "extra", - "arity": 1, - "function": "validate_sigil_p!", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "path/2", - "line": 480, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "other", - "arity": 1, - "function": "raise_invalid_route", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "guarded_unverified_url/3", - "line": 629, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint.url(), path, params", - "arity": 3, - "function": "concat_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "guarded_unverified_url/3", - "line": 628, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "url, path, params", - "arity": 3, - "function": "concat_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "guarded_unverified_url/3", - "line": 634, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint.url(), path, params", - "arity": 3, - "function": "concat_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "guarded_unverified_url/3", - "line": 638, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "URI.to_string(%{uri | path: path}), params", - "arity": 2, - "function": "append_params", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "guarded_unverified_url/3", - "line": 642, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "endpoint.url(), path, params", - "arity": 3, - "function": "concat_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "encode_segment/1", - "line": 753, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "data", - "arity": 1, - "function": "to_param", - "module": "Phoenix.Param" - } - }, - { - "caller": { - "function": "concat_url/3", - "line": 654, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "<>, params", - "arity": 2, - "function": "append_params", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "build_route/5", - "line": 935, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "meta, env", - "arity": 2, - "function": "warn_location", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "build_route/5", - "line": 933, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Phoenix.VerifiedRoutes, %{\n route: nil,\n router: router,\n warn_location: warn_location(meta, env),\n inspected_route: Macro.to_string(sigil_p),\n test_path: test_path\n}", - "arity": 2, - "function": "%", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "build_route/5", - "line": 931, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "route_ast, endpoint_ctx, router, config", - "arity": 4, - "function": "rewrite_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "build_own_forward_path/3", - "line": 1043, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path, local_script", - "arity": 2, - "function": "path_with_script", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "build_conn_forward_path/3", - "line": 1054, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "path, :erlang.++(script_name, local_script)", - "arity": 2, - "function": "path_with_script", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "append_params/2", - "line": 739, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "params", - "arity": 1, - "function": "__encode_query__", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__verify__/1", - "line": 315, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "route.test_path()", - "arity": 1, - "function": "split_test_path", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__verify__/1", - "line": 314, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Phoenix.VerifiedRoutes, %{}", - "arity": 2, - "function": "%", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 230, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__encode_segment__/1", - "line": 747, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "data", - "arity": 1, - "function": "encode_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__encode_segment__/1", - "line": 746, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "encode_segment", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__encode_query__/2", - "line": 897, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "query_str, sort?", - "arity": 2, - "function": "maybe_sort_query", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__encode_query__/2", - "line": 895, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "to_param", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "__encode_query__/2", - "line": 901, - "module": "Phoenix.VerifiedRoutes", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "val", - "arity": 1, - "function": "to_param", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "warn_if_ajax/1", - "line": 1305, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "ajax?", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "view_module/2", - "line": 604, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_safe_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "validate_local_url/1", - "line": 508, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "to", - "arity": 1, - "function": "raise_invalid_url", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "validate_local_url/1", - "line": 518, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "to", - "arity": 1, - "function": "raise_invalid_url", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "validate_jsonp_callback!/1", - "line": 437, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "t", - "arity": 1, - "function": "validate_jsonp_callback!", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "url/1", - "line": 501, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "to", - "arity": 1, - "function": "validate_local_url", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "text/2", - "line": 456, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"text/plain\", String.Chars.to_string(data)", - "arity": 4, - "function": "send_resp", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "send_resp/4", - "line": 1096, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, default_content_type", - "arity": 2, - "function": "ensure_resp_content_type", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "send_download/3", - "line": 1251, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, filename, opts", - "arity": 3, - "function": "prepare_send_download", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "send_download/3", - "line": 1260, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, filename, opts", - "arity": 3, - "function": "prepare_send_download", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "scrub_params/2", - "line": 1338, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "[key: required_key]", - "arity": 1, - "function": "exception", - "module": "Phoenix.MissingParamError" - } - }, - { - "caller": { - "function": "scrub_params/2", - "line": 1335, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Map.get(conn.params(), required_key)", - "arity": 1, - "function": "scrub_param", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "scrub_param/1", - "line": 1351, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "v", - "arity": 1, - "function": "scrub_param", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "scrub_param/1", - "line": 1356, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "", - "arity": 1, - "function": "scrub_param", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "scrub_param/1", - "line": 1360, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "param", - "arity": 1, - "function": "scrub?", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "scrub?/1", - "line": 1363, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "rest", - "arity": 1, - "function": "scrub?", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "root_layout/2", - "line": 849, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_root_layout, format", - "arity": 3, - "function": "get_private_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_with_layouts/4", - "line": 999, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "view, template, format, render_assigns", - "arity": 4, - "function": "template_render_to_iodata", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_with_layouts/4", - "line": 996, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "layout_mod, layout_base, format, root_assigns", - "arity": 4, - "function": "template_render_to_iodata", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_with_layouts/4", - "line": 994, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "view, template, format, render_assigns", - "arity": 4, - "function": "template_render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_with_layouts/4", - "line": 993, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "layout_tpl", - "arity": 1, - "function": "split_template", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_with_layouts/4", - "line": 991, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "root_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_and_send/4", - "line": 984, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, MIME.type(format)", - "arity": 2, - "function": "ensure_resp_content_type", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_and_send/4", - "line": 981, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, view, template, format", - "arity": 4, - "function": "render_with_layouts", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_and_send/4", - "line": 980, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, assigns, template, format", - "arity": 4, - "function": "prepare_assigns", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render_and_send/4", - "line": 979, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "view_module", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/4", - "line": 974, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, view", - "arity": 2, - "function": "put_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/4", - "line": 975, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "put_view(conn, view), template, assigns", - "arity": 3, - "function": "render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 951, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, format, :erlang.atom_to_binary(template), assigns", - "arity": 4, - "function": "render_and_send", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 947, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 957, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 957, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "put_format(conn, format), format, base, assigns", - "arity": 4, - "function": "render_and_send", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 956, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "template", - "arity": 1, - "function": "split_template", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/3", - "line": 966, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, view, template, []", - "arity": 4, - "function": "render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/2", - "line": 873, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, template, []", - "arity": 3, - "function": "render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/2", - "line": 877, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "action_name", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "render/2", - "line": 877, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, action_name(conn), assigns", - "arity": 3, - "function": "render", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "refuse/3", - "line": 1620, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "[\n accepts: accepted,\n message:\n <<\"no supported media type in accept header.\\n\\nExpected one of \"::binary,\n Kernel.inspect(accepted)::binary, \" but got the following formats:\\n\\n * \"::binary,\n Enum.map_join(given, \"\\n \", fn {_, header, exts} ->\n <>\n end)::binary,\n \"\\n\\nTo accept custom formats, register them under the :mime library\\nin your config/config.exs file:\\n\\n config :mime, :types, %{\\n \\\"application/xml\\\" => [\\\"xml\\\"]\\n }\\n\\nAnd then run `mix deps.clean --build mime` to force it to be recompiled.\\n\"::binary>>\n]", - "arity": 1, - "function": "exception", - "module": "Phoenix.NotAcceptableError" - } - }, - { - "caller": { - "function": "redirect/2", - "line": 496, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "Plug.Conn.put_resp_header(conn, \"location\", url), case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 302\n x -> x\nend, \"text/html\", body", - "arity": 4, - "function": "send_resp", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "redirect/2", - "line": 490, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "opts", - "arity": 1, - "function": "url", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_view/2", - "line": 537, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_view, :replace, formats", - "arity": 4, - "function": "put_private_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_secure_browser_headers/2", - "line": 1406, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "put_secure_defaults", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_secure_browser_headers/2", - "line": 1411, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "put_secure_defaults", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_root_layout/2", - "line": 794, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_root_layout, :replace, layout", - "arity": 4, - "function": "put_private_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_view/4", - "line": 553, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, priv_key, kind, formats", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_view/4", - "line": 558, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, priv_key, kind, %{_: value}", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_layout/4", - "line": 702, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, private_key, kind, formats", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_layout/4", - "line": 722, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, private_key, kind, %{_: {mod, layout}}", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_layout/4", - "line": 712, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, private_key, kind, %{_: {mod, layout}}", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_private_layout/4", - "line": 708, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, private_key, kind, %{_: false}", - "arity": 4, - "function": "put_private_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_new_view/2", - "line": 583, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_view, :new, formats", - "arity": 4, - "function": "put_private_view", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_new_layout/2", - "line": 756, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_layout, :new, layout", - "arity": 4, - "function": "put_private_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_layout/2", - "line": 652, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_layout, :replace, layout", - "arity": 4, - "function": "put_private_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_flash/3", - "line": 1706, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "flash_key", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "put_flash/3", - "line": 1706, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :maps.put(flash_key(key), message, flash)", - "arity": 2, - "function": "persist_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "prepare_send_download/3", - "line": 1268, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "warn_if_ajax", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "prepare_send_download/3", - "line": 1267, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "Keyword.get(opts, :disposition, :attachment)", - "arity": 1, - "function": "get_disposition_type", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "prepare_send_download/3", - "line": 1266, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "filename, Keyword.get(opts, :encode, true)", - "arity": 2, - "function": "encode_filename", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "prepare_assigns/4", - "line": 1023, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, assigns, format", - "arity": 3, - "function": "assigns_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "prepare_assigns/4", - "line": 1020, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "assigns", - "arity": 1, - "function": "to_map", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1571, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, t, acc, accepted", - "arity": 4, - "function": "parse_header_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1565, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1567, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, t, [{:erlang.-(q), h, exts} | acc], accepted", - "arity": 4, - "function": "parse_header_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1564, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "exts, accepted", - "arity": 2, - "function": "find_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1562, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "args", - "arity": 1, - "function": "parse_q", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1561, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "type, subtype", - "arity": 2, - "function": "parse_exts", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1579, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, acc, accepted", - "arity": 3, - "function": "refuse", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/4", - "line": 1578, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, capture, accepted", - "arity": 3, - "function": "parse_header_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/3", - "line": 1584, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "parse_header_accept/3", - "line": 1583, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "exts, accepted", - "arity": 2, - "function": "find_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "merge_flash/2", - "line": 1682, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :maps.merge(Map.get(conn.assigns(), :flash, %{}), map)", - "arity": 2, - "function": "persist_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "merge_flash/2", - "line": 1681, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "k", - "arity": 1, - "function": "flash_key", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "layout/2", - "line": 839, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, :phoenix_layout, format", - "arity": 3, - "function": "get_private_layout", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "json/2", - "line": 365, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"application/json\", response", - "arity": 4, - "function": "send_resp", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "json/2", - "line": 364, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "", - "arity": 0, - "function": "json_library", - "module": "Phoenix" - } - }, - { - "caller": { - "function": "html/2", - "line": 469, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, case conn.status() do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> 200\n x -> x\nend, \"text/html\", data", - "arity": 4, - "function": "send_resp", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "handle_params_accept/3", - "line": 1533, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, format", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "handle_params_accept/3", - "line": 1535, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "remote", - "callee": { - "args": "[\n message:\n <<\"unknown format \"::binary, Kernel.inspect(format)::binary, \", expected one of \"::binary,\n Kernel.inspect(accepted)::binary>>,\n accepts: accepted\n]", - "arity": 1, - "function": "exception", - "module": "Phoenix.NotAcceptableError" - } - }, - { - "caller": { - "function": "handle_header_accept/3", - "line": 1544, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, first", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "handle_header_accept/3", - "line": 1552, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, \"html\"", - "arity": 2, - "function": "put_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "handle_header_accept/3", - "line": 1554, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn, String.split(header, \",\"), [], accepted", - "arity": 4, - "function": "parse_header_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "get_private_layout/3", - "line": 857, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "layout_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "get_private_layout/3", - "line": 853, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_safe_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "get_flash/2", - "line": 1740, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "key", - "arity": 1, - "function": "flash_key", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "get_flash/2", - "line": 1740, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "get_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "find_format/2", - "line": 1614, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "type_range, t", - "arity": 2, - "function": "find_format", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "fetch_flash/2", - "line": 1648, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, case session_flash do\n x when :erlang.orelse(:erlang.\"=:=\"(x, false), :erlang.\"=:=\"(x, nil)) -> %{}\n x -> x\nend", - "arity": 2, - "function": "persist_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_url/2", - "line": 1889, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, params", - "arity": 2, - "function": "current_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_url/2", - "line": 1889, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn, current_path(conn, params)", - "arity": 2, - "function": "unverified_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "current_url/1", - "line": 1843, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "current_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_url/1", - "line": 1843, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "conn, current_path(conn)", - "arity": 2, - "function": "unverified_url", - "module": "Phoenix.VerifiedRoutes" - } - }, - { - "caller": { - "function": "current_path/2", - "line": 1823, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "normalized_request_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_path/2", - "line": 1827, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "normalized_request_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_path/1", - "line": 1791, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "normalized_request_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "current_path/1", - "line": 1795, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "normalized_request_path", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "clear_flash/1", - "line": 1768, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, %{}", - "arity": 2, - "function": "persist_flash", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "assigns_layout/3", - "line": 1065, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "layout_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "assigns_layout/3", - "line": 1062, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defp" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "layout_formats", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "assign/2", - "line": 1912, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, fun.(conn.assigns())", - "arity": 2, - "function": "assign", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "allow_jsonp/2", - "line": 409, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn.resp_body(), cb", - "arity": 2, - "function": "jsonp_body", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "allow_jsonp/2", - "line": 406, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn", - "arity": 1, - "function": "json_response?", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "allow_jsonp/2", - "line": 403, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "cb", - "arity": 1, - "function": "validate_jsonp_callback!", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "action_fallback/1", - "line": 315, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defmacro" - }, - "type": "remote", - "callee": { - "args": "plug, __CALLER__", - "arity": 2, - "function": "__action_fallback__", - "module": "Phoenix.Controller.Pipeline" - } - }, - { - "caller": { - "function": "accepts/2", - "line": 1527, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, Plug.Conn.get_req_header(conn, \"accept\"), accepted", - "arity": 3, - "function": "handle_header_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "accepts/2", - "line": 1524, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "local", - "callee": { - "args": "conn, format, accepted", - "arity": 3, - "function": "handle_params_accept", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "__using__/1", - "line": 237, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "defmacro" - }, - "type": "local", - "callee": { - "args": "capture, __CALLER__", - "arity": 2, - "function": "expand_alias", - "module": "Phoenix.Controller" - } - }, - { - "caller": { - "function": "__plugs__/2", - "line": 1920, - "module": "Phoenix.Controller", - "file": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "kind": "def" - }, - "type": "remote", - "callee": { - "args": "controller_module, \"Controller\"", - "arity": 2, - "function": "unsuffix", - "module": "Phoenix.Naming" - } - } - ], - "function_locations": { - "Phoenix.Logger": { - "keep_values/2:224": { - "line": 224, - "guard": null, - "pattern": "[_ | _] = list, match", - "kind": "defp", - "end_line": 225, - "ast_sha": "68b40be491818866cc341bba414ae2cca5fb86c98d3311b3042b1fb63b0a1195", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "a69c6b0b24b6b7e9cd1351f93449a34b7949d82508f39b4c1e0f1f0fc3dbe2c6", - "start_line": 224, - "name": "keep_values", - "arity": 2 - }, - "status_to_string/1:290": { - "line": 290, - "guard": null, - "pattern": "status", - "kind": "defp", - "end_line": 291, - "ast_sha": "5774021682c3e46b15005ed49240b20bd771ed30ad4d25cb94626e8280dab6b9", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "07a820bad84862e11c23b3dd2f8b6fa7eeac309b9b0eb308aef6392199542337", - "start_line": 290, - "name": "status_to_string", - "arity": 1 - }, - "phoenix_endpoint_stop/4:254": { - "line": 254, - "guard": null, - "pattern": "_, %{duration: duration}, %{conn: conn} = metadata, _", - "kind": "def", - "end_line": 263, - "ast_sha": "6959dc5fc3fa2afb0ccc73bb01eb7ea03cd0e60b2b641a571b07a4bc05aca571", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "e1120def954289075f83dd4125a1a9b5403c888cdb4e8a53bba48d5f34e78e06", - "start_line": 254, - "name": "phoenix_endpoint_stop", - "arity": 4 - }, - "log_level/2:230": { - "line": 230, - "guard": null, - "pattern": "nil, _conn", - "kind": "defp", - "end_line": 230, - "ast_sha": "2a960798449b1c5599f5bbcfbeea9f6d508f53f8fb799474ad84bb42c674c5f5", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "674f87015e517c75bbc19609b0db2864d0f5776c66740c5e751f7eec9f5f9874", - "start_line": 230, - "name": "log_level", - "arity": 2 - }, - "compile_filter/1:164": { - "line": 164, - "guard": null, - "pattern": "{:compiled, _key, _value} = filter", - "kind": "def", - "end_line": 164, - "ast_sha": "84788b066f39448036b69b6dcf8e1082524d0d55e6df457db4a71a8b90cb08f5", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "1bf5081e16d62cad797d358c3aaa0becacf6e99a15c5eea0b288ab506bc00fa9", - "start_line": 164, - "name": "compile_filter", - "arity": 1 - }, - "phoenix_socket_connected/4:343": { - "line": 343, - "guard": null, - "pattern": "_, %{duration: duration}, %{log: level} = meta, _", - "kind": "def", - "end_line": 363, - "ast_sha": "83f6dcfd03a86e2a3e3095a49939a6f251bd4afddbfb1589ebb38e90ee43db79", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "4112c3fed615f316656b55a281c89460714f847cd634a5674eac7fb2101c7561", - "start_line": 343, - "name": "phoenix_socket_connected", - "arity": 4 - }, - "phoenix_error_rendered/4:274": { - "line": 274, - "guard": null, - "pattern": "_, _, %{log: false}, _", - "kind": "def", - "end_line": 274, - "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "0b56753e8b5aa83c3c0ec63375bad252626e3b2114496671bdc6fa32eb66df0b", - "start_line": 274, - "name": "phoenix_error_rendered", - "arity": 4 - }, - "compile_filter/1:167": { - "line": 167, - "guard": null, - "pattern": "params", - "kind": "def", - "end_line": 167, - "ast_sha": "9c689b28d84f333c4cdee7c393f4b3cb01365b6f6bff6fb354fc4731f82f1999", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "a3832c125cbbe711c77bc8de135039d77cabf859b49d385018e75eba65473756", - "start_line": 167, - "name": "compile_filter", - "arity": 1 - }, - "phoenix_error_rendered/4:276": { - "line": 276, - "guard": null, - "pattern": "_, _, %{log: level, status: status, kind: kind, reason: reason}, _", - "kind": "def", - "end_line": 284, - "ast_sha": "849d763d217af8b5b0304d3ee6d308cd473ad9306894411583983dd6a456bde4", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "b5fdd2113d2d5e29a1634adc33374610dd4c6f2966f797e5d4d1f3e915fca2c8", - "start_line": 276, - "name": "phoenix_error_rendered", - "arity": 4 - }, - "discard_values/3:187": { - "line": 187, - "guard": "is_atom(mod)", - "pattern": "%{__struct__: mod} = struct, _key_match, _value_match", - "kind": "defp", - "end_line": 188, - "ast_sha": "0677344ef01535ab3968c984bfe82c08a0e95796a0dd6416b38d1db06486df73", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "eba9bf0a61e1e241a13758df2abf3b0f9cd02ff635e105f303a3f98516adc87d", - "start_line": 187, - "name": "discard_values", - "arity": 3 - }, - "discard_values/3:206": { - "line": 206, - "guard": null, - "pattern": "[_ | _] = list, key_match, value_match", - "kind": "defp", - "end_line": 207, - "ast_sha": "833900488d70e17322687554d54bafd40e3ec55d97b3574da99b2d4400d40cf1", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "e44216b6272c4a56bffa01374bc6284bc792d2502d3cc8bcb8ffb16d50f9f36d", - "start_line": 206, - "name": "discard_values", - "arity": 3 - }, - "phoenix_socket_connected/4:341": { - "line": 341, - "guard": null, - "pattern": "_, _, %{log: false}, _", - "kind": "def", - "end_line": 341, - "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "792adb559a571c69a8ada829c032e479bfa104486dc05e981675727f4b50fa46", - "start_line": 341, - "name": "phoenix_socket_connected", - "arity": 4 - }, - "mfa/3:332": { - "line": 332, - "guard": null, - "pattern": "mod, fun, arity", - "kind": "defp", - "end_line": 333, - "ast_sha": "a9ef9f73fa6db66ecc8e940c2a78f2f65802f6894d97a8cc533d2f55e39ff35e", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "56dbb18a7cacae242822f3616d60a9bed6c75d3a1b4eaa7b9fa71a92cdbc83fa", - "start_line": 332, - "name": "mfa", - "arity": 3 - }, - "log_level/2:231": { - "line": 231, - "guard": "is_atom(level)", - "pattern": "level, _conn", - "kind": "defp", - "end_line": 231, - "ast_sha": "1597b8f80a20229c8406250ebcb8adb2eeb5379ee1f66838df101b68c9faca58", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "1659a71d42ee59447b77b8d1c0eba01883f7136aa00b0a65fd465eac9a231574", - "start_line": 231, - "name": "log_level", - "arity": 2 - }, - "log_level/2:233": { - "line": 233, - "guard": "is_atom(mod) and is_atom(fun) and is_list(args)", - "pattern": "{mod, fun, args}, conn", - "kind": "defp", - "end_line": 234, - "ast_sha": "b59eb55f0ca150c83355622f4371c17e2a5e9feb3c6d144af51c0e0d8a97ae97", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "3c342dbc695a3049bc532f6a105e490ff143a0a5ef014a9cfcce216f517a7eaa", - "start_line": 233, - "name": "log_level", - "arity": 2 - }, - "join_result/1:410": { - "line": 410, - "guard": null, - "pattern": ":ok", - "kind": "defp", - "end_line": 410, - "ast_sha": "32190a99e83d7aaa14bc1a401567f0ab618b8967b812f9f7ffbc5a69f2965bca", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "4b6b5de02d004ba8fac1c98ece1df00a42a4e284b05b88809e35295886f1c207", - "start_line": 410, - "name": "join_result", - "arity": 1 - }, - "phoenix_socket_drain/4:374": { - "line": 374, - "guard": null, - "pattern": "_, %{count: count, total: total, index: index, rounds: rounds}, %{log: level} = meta, _", - "kind": "def", - "end_line": 387, - "ast_sha": "597386b08f3d3b37914a2f6a252163420dc9e49373f379389fadd49f2e665ffd", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "98d4b538ee927fe353a4d5bce273d34c37240510d4c56724d2a585d68651c1c7", - "start_line": 374, - "name": "phoenix_socket_drain", - "arity": 4 - }, - "phoenix_socket_drain/4:372": { - "line": 372, - "guard": null, - "pattern": "_, _, %{log: false}, _", - "kind": "def", - "end_line": 372, - "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "9de507e22fdf8541be2de60af8dcf1d257e879ed4fc1de5607d88f03ec3ecbb9", - "start_line": 372, - "name": "phoenix_socket_drain", - "arity": 4 - }, - "keep_values/2:214": { - "line": 214, - "guard": null, - "pattern": "%{} = map, match", - "kind": "defp", - "end_line": 219, - "ast_sha": "1df18a710793b92d6cd624a98857ce6a574ac5ff20c1ccc2c0d641b0c8780a59", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "8de1ec65730591a9b99378a536764112ed3655d323b7003c60840254d401e920", - "start_line": 214, - "name": "keep_values", - "arity": 2 - }, - "filter_values/1:180": { - "line": 180, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 180, - "ast_sha": "113b8a1a0df2de8e7d95071e8c4bfafac33683f622fabc11b738a15790a7ca8a", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "3325557b23baa8beb25a8426d6244c1fe3f313c02f940a0d5db718c74794186b", - "start_line": 180, - "name": "filter_values", - "arity": 1 - }, - "connect_result/1:369": { - "line": 369, - "guard": null, - "pattern": ":error", - "kind": "defp", - "end_line": 369, - "ast_sha": "296ddb5f8e13460f148fda58e0f433671b85a8f9a891ee9e9a512b1c52154815", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "d68858c75a274f24d2e0851560a6b54c596c129ee94b0a00769b4b9b52ce8a41", - "start_line": 369, - "name": "connect_result", - "arity": 1 - }, - "compile_discard/1:169": { - "line": 169, - "guard": null, - "pattern": "[]", - "kind": "defp", - "end_line": 170, - "ast_sha": "75a838d3a06d00955881f39afbce3399446f1821cced6ae805186ec14b1faa8b", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "27e985578d5dc24f9f75d1459ba34aa039882012ae7fd6e7307677d73034d6df", - "start_line": 169, - "name": "compile_discard", - "arity": 1 - }, - "phoenix_channel_joined/4:395": { - "line": 395, - "guard": null, - "pattern": "_, %{duration: duration}, %{socket: socket} = metadata, _", - "kind": "def", - "end_line": 405, - "ast_sha": "898abde8b42227c8eff66ad18a6ac4495716edd6fdd5d22fb0feb4007f0ee6a1", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "480bc2117d81435e6c8c0952a31e71af83a196bd29d37f80e94e1e6ffe1bdc63", - "start_line": 395, - "name": "phoenix_channel_joined", - "arity": 4 - }, - "channel_log/3:437": { - "line": 437, - "guard": null, - "pattern": "log_option, %{private: private}, fun", - "kind": "defp", - "end_line": 439, - "ast_sha": "8300185ba87a6b8eb86a8661b9dbced760f46ca5adede16941f9e4de1dd6ec71", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "485ebbffe89ae8fa01677cb260d2110700a90719b3296c3f413a1c52c1a05ec0", - "start_line": 437, - "name": "channel_log", - "arity": 3 - }, - "params/1:336": { - "line": 336, - "guard": null, - "pattern": "params", - "kind": "defp", - "end_line": 336, - "ast_sha": "d06ed9b1ba5d56e1ccc4bc90a34c2f42c36e87b78a0a6573c5a3cc96d7f9de16", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "23dd53745bc7215b8a9e8a738c489c1e864ccb61c0190346c56cd46385408747", - "start_line": 336, - "name": "params", - "arity": 1 - }, - "connection_type/1:269": { - "line": 269, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 269, - "ast_sha": "0aecfb8eb38c8094760fe4a064d5f0fe5058e42be3ac412bea9447299090ccc4", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "ebe2fef12328fad951b559fca0b59e444bb7e6d36870f1e8ac3acc619f7b92bc", - "start_line": 269, - "name": "connection_type", - "arity": 1 - }, - "phoenix_router_dispatch_start/4:302": { - "line": 302, - "guard": null, - "pattern": "_, _, metadata, _", - "kind": "def", - "end_line": 327, - "ast_sha": "e9818b047229ba922a642d0885536a2bd89e1590b1182a49aded57b84fd66737", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "1d063e890ecec5738aee7c1c0e19fcd2cfaf1343147fe67da6df834274ca1a55", - "start_line": 302, - "name": "phoenix_router_dispatch_start", - "arity": 4 - }, - "discard_values/3:191": { - "line": 191, - "guard": null, - "pattern": "%{} = map, key_match, value_match", - "kind": "defp", - "end_line": 201, - "ast_sha": "6e0df3beda4b2df3c9a416fe7b5e1dec983401622271b84b180d27c695720b30", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "8df21cce6ca24f7193aa3d543692130fe5926609a16c3c7043cb7d1ded911de9", - "start_line": 191, - "name": "discard_values", - "arity": 3 - }, - "duration/1:153": { - "line": 153, - "guard": null, - "pattern": "duration", - "kind": "def", - "end_line": 159, - "ast_sha": "c9425fc17ed83722ddadc7878ab5c6d1462a37b1d55e72e8869cb0d9ec246c97", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "2e1b3354abfc10967bc41241041a2ec5e1e2f9e634b6d3efb1b4270c3ad2e7dc", - "start_line": 153, - "name": "duration", - "arity": 1 - }, - "discard_values/3:210": { - "line": 210, - "guard": null, - "pattern": "other, _key_match, _value_match", - "kind": "defp", - "end_line": 210, - "ast_sha": "081d77d8b24c56d3d2f1ced7da9afc523a951b357f112d0a4adfbccc53a3a373", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "79c4643f47de518504ec09335482904fc60fbd6be253dbd483a530ccab646dcc", - "start_line": 210, - "name": "discard_values", - "arity": 3 - }, - "keep_values/2:212": { - "line": 212, - "guard": "is_atom(mod)", - "pattern": "%{__struct__: mod}, _match", - "kind": "defp", - "end_line": 212, - "ast_sha": "1120df37236263d86457800b69205fd82b1b2f5b312b39ae90cc9c1438ee0d3f", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "42f9aa5b4342a8cb68561423795d81df2808be81a3b738b50ce0173e6ab86728", - "start_line": 212, - "name": "keep_values", - "arity": 2 - }, - "install/0:135": { - "line": 135, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 148, - "ast_sha": "b4bd05d744e95c12f03bd04bf6f6d11d23769e28bee4bbfbf8d12950d5045738", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "832443bc7c0dd2074c684b123a39dc5bb1dae9485132267684d827bb581d4815", - "start_line": 135, - "name": "install", - "arity": 0 - }, - "error_banner/2:295": { - "line": 295, - "guard": null, - "pattern": "_kind, reason", - "kind": "defp", - "end_line": 295, - "ast_sha": "90cbc8a1793ab10ac819037a8ffbb3cd44ab1a9f5da2a4ef08f0578a15074eb5", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "666b7d1d1ee1fda45a0a91dd4a984e106cfd3b120044c577ba945fa5dba9d6db", - "start_line": 295, - "name": "error_banner", - "arity": 2 - }, - "compile_filter/1:165": { - "line": 165, - "guard": null, - "pattern": "{:discard, params}", - "kind": "def", - "end_line": 165, - "ast_sha": "8748646881577d5cb2a4a71726f6bb3fad96274c66c7fb78076656c63722c72f", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "f10ee0e9ff6c2cb9209e865314f3d1866ec8e25fbd206339229ba7ed19207d32", - "start_line": 165, - "name": "compile_filter", - "arity": 1 - }, - "phoenix_channel_handled_in/4:416": { - "line": 416, - "guard": null, - "pattern": "_, %{duration: duration}, %{socket: socket} = metadata, _", - "kind": "def", - "end_line": 430, - "ast_sha": "6dd1bcc70774f1c9ee445476f1ee8cd8bb3dd37acc84a156e49f95d527954038", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "cd786389ed0ef434fcbdc7d9f7eab180948ae8c9de7c67e38f10f0f439dcbad7", - "start_line": 416, - "name": "phoenix_channel_handled_in", - "arity": 4 - }, - "filter_values/2:180": { - "line": 180, - "guard": null, - "pattern": "values, filter", - "kind": "def", - "end_line": 183, - "ast_sha": "6fb4d6d6a0e0a19ee13f4984e30619e6e544640d8320a7a2ece98ff9c37e9b59", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "4f4aabbad998f4e5e6d2571bfcdced7496cb5b366e8f0f4c9cdf9a03223a939b", - "start_line": 180, - "name": "filter_values", - "arity": 2 - }, - "compile_filter/1:166": { - "line": 166, - "guard": null, - "pattern": "{:keep, params}", - "kind": "def", - "end_line": 166, - "ast_sha": "95c40b9b84a8f7ded2a2e6542d7ca3dca727efae38499f85e3a95bcd43cf7e7c", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "cf16ca2c9ea37d2c60ff56710665733947f51b3c3884e973938aecbf8f903351", - "start_line": 166, - "name": "compile_filter", - "arity": 1 - }, - "channel_log/3:435": { - "line": 435, - "guard": null, - "pattern": "_log_option, %{topic: <<\"phoenix\"::binary, _::binary>>}, _fun", - "kind": "defp", - "end_line": 435, - "ast_sha": "68ff3eb16325ba9ae2cfdd126d75a64ab273b7e2a9964bbee81b7cd1e1d3523f", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "3325b747ea0dc86055ba89811450a6fcdc13fbf892cc63df27889a37832cbd90", - "start_line": 435, - "name": "channel_log", - "arity": 3 - }, - "error_banner/2:294": { - "line": 294, - "guard": null, - "pattern": ":error, %type{}", - "kind": "defp", - "end_line": 294, - "ast_sha": "5bfe4307510d5c948fa935be1f3e5cfc95652af03af68cb7ab9514cb486d0f5b", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "8c24ab8c3102d483e479b4026901aecce6688c70bab202baaf2ef152376bbb13", - "start_line": 294, - "name": "error_banner", - "arity": 2 - }, - "connection_type/1:268": { - "line": 268, - "guard": null, - "pattern": ":set_chunked", - "kind": "defp", - "end_line": 268, - "ast_sha": "878054af58af03c3854cbfbe3aa0dc85c0cb7a76b82c12f1b2cfba0b2f35be71", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "b4ef0ff2a07ab53f0d8f462a841fa656ffc6466868a032dfff4927a08b7b92b8", - "start_line": 268, - "name": "connection_type", - "arity": 1 - }, - "connect_result/1:368": { - "line": 368, - "guard": null, - "pattern": ":ok", - "kind": "defp", - "end_line": 368, - "ast_sha": "0e5eff0e8624c1f68ea12c92568cd77681e338772918e02d1a627e0f05e18570", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "d945b4b2437150b33914cdc628d3a2cbc5072be60071b4777eb1427f9f406632", - "start_line": 368, - "name": "connect_result", - "arity": 1 - }, - "phoenix_router_dispatch_start/4:300": { - "line": 300, - "guard": null, - "pattern": "_, _, %{log: false}, _", - "kind": "def", - "end_line": 300, - "ast_sha": "e527326487c153aae01a4dd8d5d732fb1d4dabad91906954858463c5ee0480c8", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "f09fe4d48eacc9a1386f6da2d680a74bb7a78a5717f25b4f2037059753b1080e", - "start_line": 300, - "name": "phoenix_router_dispatch_start", - "arity": 4 - }, - "params/1:335": { - "line": 335, - "guard": null, - "pattern": "%Plug.Conn.Unfetched{}", - "kind": "defp", - "end_line": 335, - "ast_sha": "8d2dcbdb89d7028602140b682e49abb2dd544cbcecfcb9e9c5813979fe2d619e", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "3eada96a80fbc62e56e4998ec3e7c61f435136019309aae62dad5c304f15f7d2", - "start_line": 335, - "name": "params", - "arity": 1 - }, - "join_result/1:411": { - "line": 411, - "guard": null, - "pattern": ":error", - "kind": "defp", - "end_line": 411, - "ast_sha": "d8d5946e14902389bdcdb1fe8a1a4b691d346808a904899f1a9f89aa833cc6b9", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "af6eac713e5bb454ecf1dc8c303138b057080a0af99abc66fbe7583e18e4345a", - "start_line": 411, - "name": "join_result", - "arity": 1 - }, - "phoenix_endpoint_start/4:240": { - "line": 240, - "guard": null, - "pattern": "_, _, %{conn: conn} = metadata, _", - "kind": "def", - "end_line": 248, - "ast_sha": "19bd01f8d512d6d7151455aa4a27f55f9175bd5024ee9d0495b48259624a1d83", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "d39f40a75e37f08a984d2d901c916d0ec4f4cc85fb6dd287a14877962f6c29ee", - "start_line": 240, - "name": "phoenix_endpoint_start", - "arity": 4 - }, - "keep_values/2:228": { - "line": 228, - "guard": null, - "pattern": "_other, _match", - "kind": "defp", - "end_line": 228, - "ast_sha": "bbe5b75c8bd9a8ea921f149f4f342e2a6376869f30f76907583963e300c3e128", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "fc92bc9b4a1cbdc9686ea4870370c16e8dc852da193a6f354bfdf4d8dc2965ba", - "start_line": 228, - "name": "keep_values", - "arity": 2 - }, - "compile_discard/1:173": { - "line": 173, - "guard": "is_list(params) or is_binary(params)", - "pattern": "params", - "kind": "defp", - "end_line": 176, - "ast_sha": "d6fa12ede26ea199774251221986268df99c6c90352b057ddab92762f47de4ac", - "source_file": "lib/phoenix/logger.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/logger.ex", - "source_sha": "6431580bb22ce2834eda9d10e26ab2c2fa05f9c0ed4e41ddc9c6c1beaa807239", - "start_line": 173, - "name": "compile_discard", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Notifier": { - "build/1:67": { - "line": 67, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 67, - "ast_sha": "705c901ed15566e179f20f322c253981b6e0e4aaf29ca8353a57f39352f9dcad", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "a1dfdc4222ed3f6c9b3ee9a9c7283f2e0cb95e1635a65368371f1c6469653418", - "start_line": 67, - "name": "build", - "arity": 1 - }, - "build/2:67": { - "line": 67, - "guard": null, - "pattern": "args, help", - "kind": "def", - "end_line": 75, - "ast_sha": "6109f865f775f43a4d52b41565fc2a8ae13036a23097c5051a1fd4d94bbf88d2", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "42bf3fdea4ed469ff991df118801631ebb783cb50a81a3f9b02acca32d61a95d", - "start_line": 67, - "name": "build", - "arity": 2 - }, - "copy_new_files/3:159": { - "line": 159, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", - "kind": "defp", - "end_line": 164, - "ast_sha": "6907288b133e0cd3b352b54524313ac05bbf7f01644d1566b496fcc6e7fb1700", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "afd010c94b1ed0717a64e5d74c7ec68e0fbd170e41b0a5e1e3a16a66f8398c91", - "start_line": 159, - "name": "copy_new_files", - "arity": 3 - }, - "files_to_be_generated/1:167": { - "line": 167, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 170, - "ast_sha": "2949dcdc4f06a5ec7f3ceb39fd976528067b6fce797f924948459617d9058bfa", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "f8995bd9ddf6c92ebcebcddfb25bb652636701a6bfcc49f61601e64bfd2c038a", - "start_line": 167, - "name": "files_to_be_generated", - "arity": 1 - }, - "maybe_print_mailer_installation_instructions/1:182": { - "line": 182, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "def", - "end_line": 212, - "ast_sha": "3120d9941a0a7b10c5e042e6de074cd76a9dd8d591ad0fe25f333b33c17285ba", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "4a2425f2f1537773ed90b370b67cf83c791eabd8ceb53f93f1a0201d78018153", - "start_line": 182, - "name": "maybe_print_mailer_installation_instructions", - "arity": 1 - }, - "parse_opts/1:78": { - "line": 78, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 86, - "ast_sha": "ef5847c6c1e3ab919c512e20f5fa404b3e3df66f0e195d2f8141a06d615f78e3", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "b8123a54ec4f72f3259f14c695c1ff2f31703846c6de7447ad00611f6af54ed9", - "start_line": 78, - "name": "parse_opts", - "arity": 1 - }, - "prompt_for_conflicts/1:174": { - "line": 174, - "guard": null, - "pattern": "context", - "kind": "defp", - "end_line": 177, - "ast_sha": "d01037f8f96adb3720fd48df93ae5059f3d5c64ecff7611c4e157bb8bd3056ce", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "b37e08e41ebe1d8327bba055336126cf15772dc431c6ca55e3ba694a48c5a27a", - "start_line": 174, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "put_context_app/2:89": { - "line": 89, - "guard": null, - "pattern": "opts, nil", - "kind": "defp", - "end_line": 89, - "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", - "start_line": 89, - "name": "put_context_app", - "arity": 2 - }, - "put_context_app/2:91": { - "line": 91, - "guard": null, - "pattern": "opts, string", - "kind": "defp", - "end_line": 92, - "ast_sha": "9e26a188fd13878be719240f94ec8a31edd6a60160fc8b43d78c5d7349d70c5b", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", - "start_line": 91, - "name": "put_context_app", - "arity": 2 - }, - "raise_with_help/1:141": { - "line": 141, - "guard": null, - "pattern": "msg", - "kind": "def", - "end_line": 143, - "ast_sha": "7effe8c17805980aee5a55d576c9d368d357c3d492b34b03b94410691f6d11c0", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "5f7c10c313caa3d8a4aeba153a02ba0759c87d1f7164619a783b2ee39689ec7f", - "start_line": 141, - "name": "raise_with_help", - "arity": 1 - }, - "run/1:36": { - "line": 36, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 63, - "ast_sha": "346f6389231b957f8d780ccb3283d495ab415dd97da84171d579208479c9a0fd", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "9cc09178987452f0d8536931bf17bb76af6847a2dc947a7cebd987993fecf2e8", - "start_line": 36, - "name": "run", - "arity": 1 - }, - "valid_message?/1:135": { - "line": 135, - "guard": null, - "pattern": "message_name", - "kind": "defp", - "end_line": 136, - "ast_sha": "e63e87d583bf89123502fcdbfd284d0e1b7b827f9d570ce74526f0a8a1a56a89", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "949561a13cf25189b80412af5edf7cdc373b8ef60c5e5c9195254754e1d03789", - "start_line": 135, - "name": "valid_message?", - "arity": 1 - }, - "valid_notifier?/1:131": { - "line": 131, - "guard": null, - "pattern": "notifier", - "kind": "defp", - "end_line": 132, - "ast_sha": "90515a02834a5231f175582e29f49b7094db3d44f3de2b7e3021bd9d7fe290f2", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "aa895cd52ae061323c32221503250087cf7a11098204261cd80259d1e57d7a6b", - "start_line": 131, - "name": "valid_notifier?", - "arity": 1 - }, - "validate_args!/2:127": { - "line": 127, - "guard": null, - "pattern": "_, help", - "kind": "defp", - "end_line": 128, - "ast_sha": "873c8953e28d5347834106027feb65963b3938dd49d0bb5855b32b3972468eda", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "8c77bcb01e21510258efb499b659773006a6c1fcd6a2f6c7bef7270820cfbb90", - "start_line": 127, - "name": "validate_args!", - "arity": 2 - }, - "validate_args!/2:95": { - "line": 95, - "guard": null, - "pattern": "[context, notifier | messages] = args, help", - "kind": "defp", - "end_line": 123, - "ast_sha": "72607921fadc8f1cab5686bb2f2a45ad5106948a8be00488e76980b2347bc135", - "source_file": "lib/mix/tasks/phx.gen.notifier.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.notifier.ex", - "source_sha": "9aa8f782f7d97e0cf2d4fcfe545531d34b4f089545215a571089f9271466d976", - "start_line": 95, - "name": "validate_args!", - "arity": 2 - } - }, - "Phoenix.Channel": { - "__before_compile__/1:486": { - "line": 486, - "guard": null, - "pattern": "_", - "kind": "defmacro", - "end_line": 486, - "ast_sha": "2681e73c66d15ad41190c1bf9e20ad3330ea04e06714532e046445576f73f289", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "d74a491b61b94096bba5b939e58f61cfb36e6b84727a974fe3b64e1d4ad5f42d", - "start_line": 486, - "name": "__before_compile__", - "arity": 1 - }, - "__on_definition__/6:529": { - "line": 529, - "guard": "is_binary(event)", - "pattern": "env, :def, :handle_out, [event, _payload, _socket], _, _", - "kind": "def", - "end_line": 535, - "ast_sha": "e2ab875d28749e060723bb6bc5df5afc2187bc3441ff7830de74668818e46f94", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "907c38260de927da731df83940254d8b0e97698bb7e0c7a683974b65622e5931", - "start_line": 529, - "name": "__on_definition__", - "arity": 6 - }, - "__on_definition__/6:540": { - "line": 540, - "guard": null, - "pattern": "_env, _kind, _name, _args, _guards, _body", - "kind": "def", - "end_line": 540, - "ast_sha": "a75328168104ff0155e26c3705db2a3929cdc9a95afe6d899d0e2a6f6a0f7c6f", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "a4b9c486df003ba2e748a251f10640de78a9b575f7dc1254629494aab9e8d08c", - "start_line": 540, - "name": "__on_definition__", - "arity": 6 - }, - "__using__/0:450": { - "line": 450, - "guard": null, - "pattern": "", - "kind": "defmacro", - "end_line": 450, - "ast_sha": "a88f188d4c0315e5f1704c916769534fc2199c6f57ee453a573d5b48e6fe4a40", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "fb56688d827619d2515210c956b10943a26eb888dc0f0669239a3d00653a5047", - "start_line": 450, - "name": "__using__", - "arity": 0 - }, - "__using__/1:450": { - "line": 450, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 462, - "ast_sha": "46d94dfb7967ea54d34d6e49a93ceb3c5395080bd4565f42bfdb2de1e88ee8c4", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "06f82690fe3103d9cad1359dd3ecff4e00dd47d771fcd708377247354ac58f8a", - "start_line": 450, - "name": "__using__", - "arity": 1 - }, - "assert_joined!/1:698": { - "line": 698, - "guard": null, - "pattern": "%Phoenix.Socket{joined: true} = socket", - "kind": "defp", - "end_line": 699, - "ast_sha": "9c41d653dfe1a55e90b67bb38dc57a06631a5b121c27d33c90f7afb39f809b46", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "77eb24241c269531a6f0b1aaeee363ba808f128704003e98fb586cc66e578ca3", - "start_line": 698, - "name": "assert_joined!", - "arity": 1 - }, - "assert_joined!/1:702": { - "line": 702, - "guard": null, - "pattern": "%Phoenix.Socket{joined: false}", - "kind": "defp", - "end_line": 703, - "ast_sha": "8e45f082802b69e63114613a69b43b2dd24db250a30b524df7928eeb86a43d62", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "82750266954b20353bdccc689c59f0916199933616ca29e98ef06a019d7ae107", - "start_line": 702, - "name": "assert_joined!", - "arity": 1 - }, - "broadcast!/3:567": { - "line": 567, - "guard": null, - "pattern": "socket, event, message", - "kind": "def", - "end_line": 569, - "ast_sha": "97e5a25a2689cd9c3bf96d966365a61364aad009ba67ccaf115954e2f5b10805", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "42e59da1692c69404c552e4920f5a148ddca2fe52e1a31c2b0636694fcf0b1ac", - "start_line": 567, - "name": "broadcast!", - "arity": 3 - }, - "broadcast/3:559": { - "line": 559, - "guard": null, - "pattern": "socket, event, message", - "kind": "def", - "end_line": 561, - "ast_sha": "e29959bb8b0f10973016f3522ed1f5d9fce5b51bad7e6fe893ff804e1ed99085", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "fe7dfee369a962a331f272f0271cac15bbee96ddedc2fd804f36dec12cd6fd37", - "start_line": 559, - "name": "broadcast", - "arity": 3 - }, - "broadcast_from!/3:598": { - "line": 598, - "guard": null, - "pattern": "socket, event, message", - "kind": "def", - "end_line": 602, - "ast_sha": "9206e2ec20702a4a1d6a89d6112ee1d7c5fb99fb86b673e56815addda7189987", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "f6b7a60fa46cc56a489957631322b5ae2d4d682a1597727ac29ac0c093625f7b", - "start_line": 598, - "name": "broadcast_from!", - "arity": 3 - }, - "broadcast_from/3:588": { - "line": 588, - "guard": null, - "pattern": "socket, event, message", - "kind": "def", - "end_line": 592, - "ast_sha": "bc0c23ecb9d4a7798440d3dfff8697a4b9258db87add59b626d045ef58cc932c", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "ed841c8f640982bc51638cf074c45eea76fc63eedcee419d2d5ef49d652947a6", - "start_line": 588, - "name": "broadcast_from", - "arity": 3 - }, - "intercept/1:522": { - "line": 522, - "guard": null, - "pattern": "events", - "kind": "defmacro", - "end_line": 524, - "ast_sha": "19867477c386c573a513076e323a1f770cb999471e4d3d01aeb8b316104ba3e4", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "c407b3c4019abc6842da4bbee452e0ef4446bad25b227fd73579f8f11175adca", - "start_line": 522, - "name": "intercept", - "arity": 1 - }, - "push/3:628": { - "line": 628, - "guard": null, - "pattern": "socket, event, message", - "kind": "def", - "end_line": 630, - "ast_sha": "7be155e1e3f0a2ba8c461fd544f7e7ee07ae7587ca9fbf1a3b741aa3979350fb", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "daaaa8334577f1ecebc89779ea39342cbd3d67060803bfac5614a03f6b2b2624", - "start_line": 628, - "name": "push", - "arity": 3 - }, - "reply/2:674": { - "line": 674, - "guard": "is_atom(status)", - "pattern": "socket_ref, status", - "kind": "def", - "end_line": 675, - "ast_sha": "d83ea14569b5699211215852f9fa195552640bdd6551a5054a4b8a86ba0203a2", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "8075f715f38dd601ee6e7c27c0d1781f85d763c9916ecafc29d8dfb605a5a605", - "start_line": 674, - "name": "reply", - "arity": 2 - }, - "reply/2:678": { - "line": 678, - "guard": null, - "pattern": "{transport_pid, serializer, topic, ref, join_ref}, {status, payload}", - "kind": "def", - "end_line": 679, - "ast_sha": "1c7b424fa75e7108de8dc3c76bbc7fcaf1fce043261de587ec035743e3e7d67c", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "6130ba990f1d3d2da0f3c1004cdfe8f8dea19df6654d92e83a0c1941fb0c1a44", - "start_line": 678, - "name": "reply", - "arity": 2 - }, - "socket_ref/1:688": { - "line": 688, - "guard": "not (ref == nil)", - "pattern": "%Phoenix.Socket{joined: true, ref: ref} = socket", - "kind": "def", - "end_line": 689, - "ast_sha": "e4af2ad51e49dc122b6c3b3ed63a1812346e8b61f65a1ab9bf501c0a71c2e064", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "59a6dd03576fecc9f0a9e292f797c86d3a4f29ba85d810d7c9fd60edd44d8c54", - "start_line": 688, - "name": "socket_ref", - "arity": 1 - }, - "socket_ref/1:692": { - "line": 692, - "guard": null, - "pattern": "_socket", - "kind": "def", - "end_line": 693, - "ast_sha": "404cca7a186852e83e0880c5e25d0c998707b0ee6af78af0908ea06dc51ce300", - "source_file": "lib/phoenix/channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel.ex", - "source_sha": "2d41e437323adf06abdb31411c1b5166e1ef016c035a0ccd701d5a025162f4d6", - "start_line": 692, - "name": "socket_ref", - "arity": 1 - } - }, - "Phoenix.Channel.Server": { - "handle_info/2:356": { - "line": 356, - "guard": null, - "pattern": "{:DOWN, ref, _, _, reason}, ref", - "kind": "def", - "end_line": 357, - "ast_sha": "2864b3427ab1674bb98488f49995cb655c5fe59271b504bdc98724b95162629e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "be0165ddfe906dd8741986ad0375568fa5dc384355711be85a757e54f6f50a0c", - "start_line": 356, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:339": { - "line": 339, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{event: \"phx_drain\"}, %{transport_pid: transport_pid} = socket", - "kind": "def", - "end_line": 344, - "ast_sha": "f3683150a7f605d0a284f6dfb289768c3e29eccebd5c1cd3c1caf1a6aba08b60", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "11d4019583aaa867a7bf54f6e00cac2c6556f57013f299baaf00b41e8e8fee1e", - "start_line": 339, - "name": "handle_info", - "arity": 2 - }, - "socket/1:66": { - "line": 66, - "guard": null, - "pattern": "pid", - "kind": "def", - "end_line": 67, - "ast_sha": "a8a2104af65076c3a4b11e936c86950916bdd0dc93deeb410f4f6dfc266ea6c1", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "c850a02269f1d08b1ca51240add4c61ac189d2b3f1985306f83dce8a5b3dfe75", - "start_line": 66, - "name": "socket", - "arity": 1 - }, - "broadcast!/4:163": { - "line": 163, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, topic, event, payload", - "kind": "def", - "end_line": 171, - "ast_sha": "6f0fa5514d5033d1f47efe1c14b49541a2539dd7cfd46c6f2a6ef00284c9b571", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "daf8827b355f2420ab9df6ec01535a71715e21f7734635f5dcd3c2a9bd0be824", - "start_line": 163, - "name": "broadcast!", - "arity": 4 - }, - "handle_in/1:513": { - "line": 513, - "guard": null, - "pattern": "{:reply, reply, %Phoenix.Socket{} = socket}", - "kind": "defp", - "end_line": 515, - "ast_sha": "a1164ec0ee0282fa8624e94f5eaa1856c356fd4ca76f0494c53e197541a8e02c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "6f7f8236fc9361fc7d00b96366fdb2d03267c71d84fe6dd0cdf625fa155b43cb", - "start_line": 513, - "name": "handle_in", - "arity": 1 - }, - "push/6:248": { - "line": 248, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pid, join_ref, topic, event, payload, serializer", - "kind": "def", - "end_line": 251, - "ast_sha": "2197d80a9ce3c753b1bdba78e6d371c0d46b0a81adc7401e2954378250689109", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "f708e132170922cc628453c15cf81159c50436085f8ad472e64b924ed0130dbb", - "start_line": 248, - "name": "push", - "arity": 6 - }, - "local_broadcast_from/5:231": { - "line": 231, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, from, topic, event, payload", - "kind": "def", - "end_line": 239, - "ast_sha": "014942d44ff4d60b6be655cb9e43d5c51f54c5d372381504a815eaf1a2f45940", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "ddb5e756d20d3bea82e47ba37684cef5045b3b4978d527e9d5731ac0d96a2dec", - "start_line": 231, - "name": "local_broadcast_from", - "arity": 5 - }, - "local_broadcast/4:214": { - "line": 214, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, topic, event, payload", - "kind": "def", - "end_line": 222, - "ast_sha": "65588d77cd2b410fb1bdfdb0624df2cd4aa524c457d189fd8edd9fe0a04a6181", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "68730c2a86acd98506f16d5dd0d1e795b1db3523ce53a72cfe4405e6715fe84b", - "start_line": 214, - "name": "local_broadcast", - "arity": 4 - }, - "reply/6:260": { - "line": 260, - "guard": "is_binary(topic)", - "pattern": "pid, join_ref, ref, topic, {status, payload}, serializer", - "kind": "def", - "end_line": 263, - "ast_sha": "e700ddece593e28bbbb5b4f7779a2b342dbe178c629e4cc351e7b54377a8d5c2", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "e6172d894b8460cb6f9b04eb5ef9c141ba42fc489658bacdbfdc9c32eef1cd51", - "start_line": 260, - "name": "reply", - "arity": 6 - }, - "handle_info/2:365": { - "line": 365, - "guard": null, - "pattern": "msg, %{channel: channel} = socket", - "kind": "def", - "end_line": 372, - "ast_sha": "345868b6fc301f38372aeb21e8616390c76074a90216a7d794511f53ba27cf0e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "f72099ba4bca6fde73dda0b3fc57348556f06257d522d62cbad43229ab948883", - "start_line": 365, - "name": "handle_info", - "arity": 2 - }, - "handle_result/2:462": { - "line": 462, - "guard": null, - "pattern": "{:reply, resp, socket}, :handle_call", - "kind": "defp", - "end_line": 463, - "ast_sha": "2c3c0908d9fe0cd1f5d413ef24cebef3c85e9c58a66fd9f7ae9e82f0bd391729", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "163171b2deb8671472af3d44721d872aad909d3cb44f3dd746691f4df415e342", - "start_line": 462, - "name": "handle_result", - "arity": 2 - }, - "handle_result/2:495": { - "line": 495, - "guard": null, - "pattern": "result, callback", - "kind": "defp", - "end_line": 503, - "ast_sha": "813906960c4a617106fa96223f34b160796b581cd41740c144786bbeaa739e93", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "fa5bbd8da4e276066d5226c2a9208ed91527f736b9855057bbc6de74aa186bd8", - "start_line": 495, - "name": "handle_result", - "arity": 2 - }, - "warn_unexpected_msg/4:559": { - "line": 559, - "guard": null, - "pattern": "fun, arity, msg, channel", - "kind": "defp", - "end_line": 568, - "ast_sha": "1a483d5ef0d15aeebc8725ab9c711a17d223b7b51a7e64439b7c60c28f1093b4", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "dbfef733babb2ac352b35101bba650c8e33793be7a102d7315b7e7518f117ed2", - "start_line": 559, - "name": "warn_unexpected_msg", - "arity": 4 - }, - "handle_result/2:479": { - "line": 479, - "guard": null, - "pattern": "result, :handle_in", - "kind": "defp", - "end_line": 491, - "ast_sha": "f2a2c7a8e31d30441feff82ac5683647653944f2beb14569b28a1dd73eb01643", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "b9a190edb87fcb9583cdbe31478bfdfa8724f22d0aa7ade3b1f926087670f4b7", - "start_line": 479, - "name": "handle_result", - "arity": 2 - }, - "handle_reply/2:538": { - "line": 538, - "guard": "is_atom(status)", - "pattern": "socket, status", - "kind": "defp", - "end_line": 539, - "ast_sha": "8461e06f715bacddb00e5b7b52fe2d37e182566e1ed6b80540d5b713fb3752b8", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "493e5edf87484d7c4af48244cd2c43a78b455443afa5b7308b3c78b3c7f1e909", - "start_line": 538, - "name": "handle_reply", - "arity": 2 - }, - "handle_result/2:466": { - "line": 466, - "guard": "=:=(callback, :handle_call) or =:=(callback, :handle_cast)", - "pattern": "{:noreply, socket}, callback", - "kind": "defp", - "end_line": 468, - "ast_sha": "27d0d44f570815648e7d54013f34b01fa3beb8ee641dccded9d15f56d8cbe72a", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "7529e5cf40a59313bd5ff30f839180b0df082302e948ccb41f468b07069ffc4b", - "start_line": 466, - "name": "handle_result", - "arity": 2 - }, - "dispatch/3:124": { - "line": 124, - "guard": null, - "pattern": "entries, :none, message", - "kind": "def", - "end_line": 126, - "ast_sha": "258bd7ea6db3a50c0ecdd80b7c4297e8ee3e9610a3300a00d9d1b5157830f87e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "0bd1cbaaa940f7f983bacfa47d889fcb45378219ac421d13e046a850fcf54560", - "start_line": 124, - "name": "dispatch", - "arity": 3 - }, - "handle_info/2:327": { - "line": 327, - "guard": null, - "pattern": "%Phoenix.Socket.Message{topic: topic, event: event, payload: payload, ref: ref}, %{topic: topic} = socket", - "kind": "def", - "end_line": 336, - "ast_sha": "81780e05ebae193c23a513a08adfaee07e2b64d8f89ce883e917b32577054365", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "d0cb7503f9d026e5b183d4ac800b0621f42dc8add8dfd37310c0d92b4bf08858", - "start_line": 327, - "name": "handle_info", - "arity": 2 - }, - "handle_cast/2:287": { - "line": 287, - "guard": null, - "pattern": ":close, socket", - "kind": "def", - "end_line": 288, - "ast_sha": "a0d5d5b76106a093249b7ea099cc50cfd365ee1459b6f69097fac68589025fc6", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "0d9cad59ed0be5bc2d3c46d496b90cb5fa7e3e558284845b55f00db95ae4a9f2", - "start_line": 287, - "name": "handle_cast", - "arity": 2 - }, - "handle_call/3:275": { - "line": 275, - "guard": null, - "pattern": ":socket, _from, socket", - "kind": "def", - "end_line": 276, - "ast_sha": "51f9cd965dfcaa9196ce3f40d0fd38baf296d251fe0bace509432f3dab941a0c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "431603d546d3427cf78af67d803d09ee00dcfcbb6fe8d778840ea5884b650408", - "start_line": 275, - "name": "handle_call", - "arity": 3 - }, - "handle_reply/2:542": { - "line": 542, - "guard": null, - "pattern": "_socket, reply", - "kind": "defp", - "end_line": 555, - "ast_sha": "60169b474ab4b72215b56575a95b91997ef6857ce3fb35f73173f4f90ced904c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "2b8317de20222e256962825b319b1dc5baf67d726f80163ebcf7a44fde3e867f", - "start_line": 542, - "name": "handle_reply", - "arity": 2 - }, - "code_change/3:377": { - "line": 377, - "guard": null, - "pattern": "old, %{channel: channel} = socket, extra", - "kind": "def", - "end_line": 381, - "ast_sha": "6bbee65557679547094ccabf38aa619720f562b6418229eb484009b4c2c3e399", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "809027b39e2d8323df4cd5e3b0e3e1d05242a5710ceb5629047bab43f8e7e03a", - "start_line": 377, - "name": "code_change", - "arity": 3 - }, - "handle_cast/2:292": { - "line": 292, - "guard": null, - "pattern": "msg, socket", - "kind": "def", - "end_line": 295, - "ast_sha": "760183522fdf147229dd92f207b45194c6f0e5e27cc696216cb31b9ee0731b6f", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "0bb515c63bc6e1ece8699dd99c444c3188526a354f8e555a53218d0219e462c0", - "start_line": 292, - "name": "handle_cast", - "arity": 2 - }, - "handle_reply/2:527": { - "line": 527, - "guard": "is_atom(status)", - "pattern": "socket, {status, payload}", - "kind": "defp", - "end_line": 534, - "ast_sha": "7e7fdfc39535fd814d74c685864d3dd7d7facf250bd3961a55b23a4de8be59b8", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "c90f75a3cd57da334d1de9fe0e853ff6057670f7b7776aef21982a708fbfed6e", - "start_line": 527, - "name": "handle_reply", - "arity": 2 - }, - "handle_result/2:471": { - "line": 471, - "guard": null, - "pattern": "{:noreply, socket}, _callback", - "kind": "defp", - "end_line": 472, - "ast_sha": "03edfa045df20d8e6db35bd75a6281e3d368a909b0c978ec7692994957ec485f", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "5ed5145658312d82843018e0586aec4a6d94cc75c4cdff98eb6b8b058a268d45", - "start_line": 471, - "name": "handle_result", - "arity": 2 - }, - "dispatch/3:132": { - "line": 132, - "guard": null, - "pattern": "entries, from, message", - "kind": "def", - "end_line": 134, - "ast_sha": "92d59f958c26ef2fd03286b9701819569110a91859c637fe518f67fb7964297e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "8195368492dd2442f82b4b92d725c43c70dfa51505813fc08417bb2188e8d5df", - "start_line": 132, - "name": "dispatch", - "arity": 3 - }, - "join/4:17": { - "line": 17, - "guard": null, - "pattern": "socket, channel, message, opts", - "kind": "def", - "end_line": 56, - "ast_sha": "ecc723b55b1956bfcf794e6e0d18367d1d3052e8b181993c0449b0eeddbdc2ec", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "d2f03cbfe9bad2ac4edd3bc19c04575588364d00b93eeb3ba30464671ad01265", - "start_line": 17, - "name": "join", - "arity": 4 - }, - "broadcast/4:146": { - "line": 146, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, topic, event, payload", - "kind": "def", - "end_line": 154, - "ast_sha": "40cc5edad94182bdffb1c8a7bfe17109675934346f65d651e44938dbafee926c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "5754ab166fd26b55bb52771f91e528a862c7e85c4df49dd2826e79a6d324bca5", - "start_line": 146, - "name": "broadcast", - "arity": 4 - }, - "terminate/2:386": { - "line": 386, - "guard": null, - "pattern": "reason, %{channel: channel} = socket", - "kind": "def", - "end_line": 388, - "ast_sha": "45c61bd47e8bef03718d0d7374093e900e3e85357159e30905feb89b3367f76e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "d10285df9ccf585d63bd97d840a0380568024e8aa13d65deed320437944f58dd", - "start_line": 386, - "name": "terminate", - "arity": 2 - }, - "handle_info/2:323": { - "line": 323, - "guard": null, - "pattern": "%Phoenix.Socket.Message{topic: topic, event: \"phx_leave\", ref: ref}, %{topic: topic} = socket", - "kind": "def", - "end_line": 324, - "ast_sha": "798b269f226e8192301d1a61c44865d80cb847c452340ea503e3904f71681856", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "d1209a07685b705c4fff43d73fa416c7d3a3420381cef57bc2438081aa851af7", - "start_line": 323, - "name": "handle_info", - "arity": 2 - }, - "channel_join/4:400": { - "line": 400, - "guard": null, - "pattern": "channel, topic, auth_payload, socket", - "kind": "defp", - "end_line": 419, - "ast_sha": "55ea2c60c615b00dc2f31234241dc5f631727fdfb3c9eb5ebd53ae61ac7eb720", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "b3b46642ef56a388275141723263006fac2d6ab7ef281984ae56213e098222f7", - "start_line": 400, - "name": "channel_join", - "arity": 4 - }, - "handle_in/1:518": { - "line": 518, - "guard": null, - "pattern": "{:stop, reason, reply, socket}", - "kind": "defp", - "end_line": 520, - "ast_sha": "ca382441c48d21c656a4e6ec56d63bffbe8241872af7af448f6dac54b885a5fd", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "56203d1fae92f66b94f12eaa3925bf803dd25104fc606a23776203c2c583a08e", - "start_line": 518, - "name": "handle_in", - "arity": 1 - }, - "handle_info/2:299": { - "line": 299, - "guard": null, - "pattern": "{Phoenix.Channel, auth_payload, {pid, _} = from, socket}, ref", - "kind": "def", - "end_line": 320, - "ast_sha": "634b3105b588fad6c067e00de33d23f565393644ff98215b8a7a935db3975845", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "f0353694a4fbd00cb5f858570d95c148f367249df2cd277aa7c0041f8468975a", - "start_line": 299, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:360": { - "line": 360, - "guard": null, - "pattern": "{:DOWN, _, _, transport_pid, reason}, %{transport_pid: transport_pid} = socket", - "kind": "def", - "end_line": 362, - "ast_sha": "e20347f264339ccfbddbdf7485780e56c26c511ba078d7739d2612a204473d56", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "a3aee8adce2128a945b3fa0054bbb0d58e74172eeb19d2520640a744be40cd34", - "start_line": 360, - "name": "handle_info", - "arity": 2 - }, - "broadcast_from/5:180": { - "line": 180, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, from, topic, event, payload", - "kind": "def", - "end_line": 188, - "ast_sha": "6ab0b7db49c1933ac5151a2d0d9b1cb1b48096cb870aead285e882243fca887c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "721c806e583f170885a9e4bef17701a5155e4db02e2f461be481015e98e14eb2", - "start_line": 180, - "name": "broadcast_from", - "arity": 5 - }, - "dispatch/3:94": { - "line": 94, - "guard": null, - "pattern": "subscribers, from, %Phoenix.Socket.Broadcast{event: event} = msg", - "kind": "def", - "end_line": 118, - "ast_sha": "f37fb347576027e16ec33628afa48f8172a1e65186a974ee9acf6f7865696af2", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "202bc9e1a8a0f744ea565d4236af2ba5835eb81b84ad093efc8f229d46ba1cc1", - "start_line": 94, - "name": "dispatch", - "arity": 3 - }, - "close/2:76": { - "line": 76, - "guard": null, - "pattern": "pid, timeout", - "kind": "def", - "end_line": 85, - "ast_sha": "5fe5fc74a35e30f292e6dd041039ca09d8bfad9f2766c6ab31712163fe40415e", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "7998e35efe2a9df29edd6db9b9bf88b1eb1f6c92565afe4483f0f175b1309383", - "start_line": 76, - "name": "close", - "arity": 2 - }, - "handle_info/2:347": { - "line": 347, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{topic: topic, event: event, payload: payload}, %Phoenix.Socket{topic: topic} = socket", - "kind": "def", - "end_line": 353, - "ast_sha": "efb9eb36b2e2dc78dd0e4a027de84fca1717ed4f0b1f2d90641acf78d583f5dd", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "fa2de837f4c13a56ab54699469e902aa3dbfceec6e5de8f45cbe0e3e987bf803", - "start_line": 347, - "name": "handle_info", - "arity": 2 - }, - "handle_in/1:523": { - "line": 523, - "guard": null, - "pattern": "other", - "kind": "defp", - "end_line": 524, - "ast_sha": "00414c7f2a4e40fb733da52ddc158e19b2fb28314e47a57dcc6fb98d102eb790", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "6ca51be18d1112b9135be2b758055ec3be67fef450953c1a530db00a1fcf55e5", - "start_line": 523, - "name": "handle_in", - "arity": 1 - }, - "handle_result/2:451": { - "line": 451, - "guard": null, - "pattern": "{:stop, reason, socket}, _callback", - "kind": "defp", - "end_line": 459, - "ast_sha": "0122a2506ca91eca51146a45d6a0eb38c924fc5f028c90fab2f273bb75a0bf7c", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "50e6d144194f0482e54d52e8e01809685c8a533150b4bf8a236b247558bd9d88", - "start_line": 451, - "name": "handle_result", - "arity": 2 - }, - "handle_result/2:475": { - "line": 475, - "guard": null, - "pattern": "{:noreply, socket, timeout_or_hibernate}, _callback", - "kind": "defp", - "end_line": 476, - "ast_sha": "11971865ef9b7bc3076dc9b68daf0d1970c1a3c401fa9acaae12a43ea6aca0d9", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "c437e8fdbdf46e10f827a5dc1c8d6a2585ec44c808a87706809354d5c361ffce", - "start_line": 475, - "name": "handle_result", - "arity": 2 - }, - "init_join/3:424": { - "line": 424, - "guard": null, - "pattern": "socket, channel, topic", - "kind": "defp", - "end_line": 446, - "ast_sha": "796becaaa31e2427b13a0dd29f682f57bcf4a32e29d23b4ce0dfc191ae2d7bb6", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "f09b7bca6bff94176936bbb08c96de02b77a0aff861377927da9aef854547606", - "start_line": 424, - "name": "init_join", - "arity": 3 - }, - "child_spec/1:3": { - "line": 3, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 862, - "ast_sha": "8ed3b2567eb1d06b5e1ddc8a65a6fda3af1902657743e8155a087b9678ec6105", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "9baecdee4a37fc795d674d5fa917e41b41242ec3928f13aeabcfb0f72273fc95", - "start_line": 3, - "name": "child_spec", - "arity": 1 - }, - "terminate/2:394": { - "line": 394, - "guard": null, - "pattern": "_reason, _socket", - "kind": "def", - "end_line": 394, - "ast_sha": "6ea9d1f3cbeeae2b7a87faee305df151f31a28a68533071af2ad45a09374cef3", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "aa96a888a94fc12b44493c46c7cff2b23081f75819653164f5ce33e7680eaaf7", - "start_line": 394, - "name": "terminate", - "arity": 2 - }, - "handle_call/3:280": { - "line": 280, - "guard": null, - "pattern": "msg, from, socket", - "kind": "def", - "end_line": 283, - "ast_sha": "e17317653bc0e2011d3652902c9b171efdaf320a36915673fd988e6f5db1dcf1", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "2df235356d7ae8f71d806ca682a12eb017c9c64bdc8bca5fe36e734d19421aaf", - "start_line": 280, - "name": "handle_call", - "arity": 3 - }, - "send_socket_close/2:507": { - "line": 507, - "guard": null, - "pattern": "%{transport_pid: transport_pid}, reason", - "kind": "defp", - "end_line": 508, - "ast_sha": "f90e65f839ffc6dea598583ef1c983f174b735b828d77c76f3e9ea58a7a773dd", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "42c2725dd46339039e36ef915cbfbe1b5f9083e41ae2051433ff11ee90895337", - "start_line": 507, - "name": "send_socket_close", - "arity": 2 - }, - "init/1:270": { - "line": 270, - "guard": null, - "pattern": "{_endpoint, {pid, _}}", - "kind": "def", - "end_line": 271, - "ast_sha": "73a59c0d656af0d2c6422e1ee6b17ace135c1300274eae83f1442c666892e452", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "5147737227f3adb4a6dcb04481dc9520a7f04407cd4cfa8f8d895fcafe44938c", - "start_line": 270, - "name": "init", - "arity": 1 - }, - "broadcast_from!/5:197": { - "line": 197, - "guard": "is_binary(topic) and is_binary(event)", - "pattern": "pubsub_server, from, topic, event, payload", - "kind": "def", - "end_line": 205, - "ast_sha": "ba85984c3b82d131589c825723bb3f3ed82d705a087d6630ebceeb76b5d97fbb", - "source_file": "lib/phoenix/channel/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/channel/server.ex", - "source_sha": "0844b18a51d12f499ac8be17a8a55a17b9839fb1565a6dd3270cf64b3b92007f", - "start_line": 197, - "name": "broadcast_from!", - "arity": 5 - } - }, - "Phoenix.Socket.PoolDrainer": { - "child_spec/1:70": { - "line": 70, - "guard": null, - "pattern": "{_endpoint, name, opts} = tuple", - "kind": "def", - "end_line": 77, - "ast_sha": "95914fac4507e7f20bf92f804729f0de26f9bfaf312da9a37d07458e37d6d1d3", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "074b9ef9a9d675c53eb58b8267389327d10ed5425f6f0f5fe2972eb90814ecff", - "start_line": 70, - "name": "child_spec", - "arity": 1 - }, - "code_change/3:68": { - "line": 68, - "guard": null, - "pattern": "_old, state, _extra", - "kind": "def", - "end_line": 940, - "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", - "start_line": 68, - "name": "code_change", - "arity": 3 - }, - "handle_call/3:68": { - "line": 68, - "guard": null, - "pattern": "msg, _from, state", - "kind": "def", - "end_line": 884, - "ast_sha": "d154285ffa31c40a154abcc529ee5f8e6b815c60b9c4c00bbba52fd368dd5b68", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", - "start_line": 68, - "name": "handle_call", - "arity": 3 - }, - "handle_cast/2:68": { - "line": 68, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 929, - "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", - "start_line": 68, - "name": "handle_cast", - "arity": 2 - }, - "handle_info/2:68": { - "line": 68, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 912, - "ast_sha": "f3a7db135487577a5363abbd102490541da1764a380f1536439d2b72f2d79c40", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "cbefbb64e11bc08694b04a491e859147d4d473b0a0107d4cdfb6cf88f1710e8f", - "start_line": 68, - "name": "handle_info", - "arity": 2 - }, - "init/1:86": { - "line": 86, - "guard": null, - "pattern": "{endpoint, name, opts}", - "kind": "def", - "end_line": 91, - "ast_sha": "3b9c622985d1798e8ead8081dad06ee3a3909b4c2a03379340453479b6153edc", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "36a6fd3260e3b430efa08638fbd7347e3c50643d1a95bd2693a43cd6263f6876", - "start_line": 86, - "name": "init", - "arity": 1 - }, - "start_link/1:81": { - "line": 81, - "guard": null, - "pattern": "tuple", - "kind": "def", - "end_line": 82, - "ast_sha": "0a02109cfaaf725e2dc8aaac31c7b9e8cb37868a6073c92ac356c8d46f20afa5", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "46101793a503a33028b0f7fe31e1d38b20c342fa40a48002926eb542315db8b6", - "start_line": 81, - "name": "start_link", - "arity": 1 - }, - "terminate/2:95": { - "line": 95, - "guard": null, - "pattern": "_reason, {endpoint, name, size, interval, log_level}", - "kind": "def", - "end_line": 134, - "ast_sha": "084756897ce61b1727d3b9b2cabcece5c85cea40d436b5529b43a001250ff01f", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "418c8bade3923aa879162a128962380fc5038f4d9ddac474d7f4f03b87f0f7ae", - "start_line": 95, - "name": "terminate", - "arity": 2 - } - }, - "Phoenix.Controller": { - "ajax?/1:1297": { - "line": 1297, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 1300, - "ast_sha": "c2fb29f19e90e578e9a1e8afc5604d24aebeca5a198485c46909a08a3c13f823", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a1fd2bbe1bb6685907b307f9d1ebfd9e44176712565ac438f14ee9e811520eba", - "start_line": 1297, - "name": "ajax?", - "arity": 1 - }, - "render/1:870": { - "line": 870, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 870, - "ast_sha": "b970187717539c65106bb48d7236f5a4f1cda332bb7b38b12cd81123a97b2e87", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "dd860040f378e1fbc8c60b22797bedd0f9f68bce1e17b71513b16800a3012cbd", - "start_line": 870, - "name": "render", - "arity": 1 - }, - "put_private_formats/4:561": { - "line": 561, - "guard": "=:=(kind, :new) or =:=(kind, :replace)", - "pattern": "conn, priv_key, kind, formats", - "kind": "defp", - "end_line": 571, - "ast_sha": "7d129ec2fd2fb21b2a1b7dcc98972f7c9a1ea9e0bf03229ae24205f7af3d7c86", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fbd1dbc700f7c30681b6d3e475967ad8877ae2efce2a0b70a3146fc8164ed059", - "start_line": 561, - "name": "put_private_formats", - "arity": 4 - }, - "put_root_layout/2:792": { - "line": 792, - "guard": null, - "pattern": "%Plug.Conn{state: state} = conn, layout", - "kind": "def", - "end_line": 802, - "ast_sha": "be611d95bf1f1f3a691a2949a91503ff2e25919ab441e9f7c483aef014fcfff7", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2a4b040694706ad18c43f822eb5d01b866af7da88601522967471a3af2f5cedd", - "start_line": 792, - "name": "put_root_layout", - "arity": 2 - }, - "put_router_url/2:1135": { - "line": 1135, - "guard": "is_binary(url)", - "pattern": "conn, url", - "kind": "def", - "end_line": 1136, - "ast_sha": "a190af816e0ce1c8d1aea600683f9a8b79cc9a537ac5982f7ebf8b959e5d842d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "50a9e7507bbec344c41a58b50fe16094429e171d4f1e252d212b0ab07918a30f", - "start_line": 1135, - "name": "put_router_url", - "arity": 2 - }, - "handle_header_accept/3:1543": { - "line": 1543, - "guard": "header == [] or header == [\"*/*\"]", - "pattern": "conn, header, [first | _]", - "kind": "defp", - "end_line": 1544, - "ast_sha": "7e3d33d92abc9606356c3b55c0e2b9548c57b650b140e9f6c508c9fbd5782db4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "976ddbf017bcb8ac4bf62636391942dd4c28fa2d4592cfc524bc242e85ae27a9", - "start_line": 1543, - "name": "handle_header_accept", - "arity": 3 - }, - "put_view/2:536": { - "line": 536, - "guard": "=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)", - "pattern": "%Plug.Conn{state: state} = conn, formats", - "kind": "def", - "end_line": 537, - "ast_sha": "cbcb35d79ba28dc88d34a0b1294f1fa8591747cb9cb826fbace8cb32fe742459", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e5c1a9fd5e79adff20a0dac6a2a1b76ceccaef80b0c6ebea82fb24cdcece35dd", - "start_line": 536, - "name": "put_view", - "arity": 2 - }, - "allow_jsonp/1:392": { - "line": 392, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 392, - "ast_sha": "c5510ef8d68f5585f53e7820a9e5fcd5ceb2658b65d15f29888692bca4555174", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "b284b2563d0d6ada4aa3e62f2ff533517020d4836e0f81555be6e1189fd30752", - "start_line": 392, - "name": "allow_jsonp", - "arity": 1 - }, - "put_flash/3:1701": { - "line": 1701, - "guard": null, - "pattern": "conn, key, message", - "kind": "def", - "end_line": 1706, - "ast_sha": "f32417e9d5a7e9bcbe5557f7c7420c12ee01dad2faa5c7f8fc34f8d966f5ba4d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "854dcfd5df4dc0952e8b6854444aa1c9007b83226b0bf16d29a2ed4649b66a92", - "start_line": 1701, - "name": "put_flash", - "arity": 3 - }, - "__using__/1:234": { - "line": 234, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 242, - "ast_sha": "d9cb19fbe8d224c81533921bead5636aff5a18a154772d0797713a6c61815014", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "1b88dcc851de6d39cda303befaf3069479646f6c92be38085922d977394c126b", - "start_line": 234, - "name": "__using__", - "arity": 1 - }, - "put_secure_browser_headers/2:1405": { - "line": 1405, - "guard": null, - "pattern": "conn, []", - "kind": "def", - "end_line": 1406, - "ast_sha": "331e24e4e7e3f2bef3ef63cc704124309024fdbf4dad21015c206793ced4efda", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a9c79259f61af57db66838a2fea995a65827a731311fa37138fc5a4482796ac7", - "start_line": 1405, - "name": "put_secure_browser_headers", - "arity": 2 - }, - "validate_local_url/1:518": { - "line": 518, - "guard": null, - "pattern": "to", - "kind": "defp", - "end_line": 518, - "ast_sha": "35a9c04127fb190a28ee0a2f5909994b52b78a746be6be9fe008446fc4ebf877", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "385340f1d941c42101fdfa45a100fcc530672f2168185d6483b0b5b5634c7dc9", - "start_line": 518, - "name": "validate_local_url", - "arity": 1 - }, - "text/2:455": { - "line": 455, - "guard": null, - "pattern": "conn, data", - "kind": "def", - "end_line": 456, - "ast_sha": "002d2b26f6c080f0a60c77442c873f21798e964827993d9dbba897b9a9373046", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "d148235ee4f803762c2d81fb04a527dc232dbcd4df0afef827fb31f6b1b7ce68", - "start_line": 455, - "name": "text", - "arity": 2 - }, - "ensure_resp_content_type/2:1100": { - "line": 1100, - "guard": null, - "pattern": "%Plug.Conn{resp_headers: resp_headers} = conn, content_type", - "kind": "defp", - "end_line": 1105, - "ast_sha": "60c4d290261d2c703255b298c1a9c4c53fd7a9881961f295f3af0db138d694d8", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "28d36ad3b44067b6d3b443b8b2bc57b17595c9522b75b60b57b4812169fa92ee", - "start_line": 1100, - "name": "ensure_resp_content_type", - "arity": 2 - }, - "send_download/3:1255": { - "line": 1255, - "guard": null, - "pattern": "conn, {:binary, contents}, opts", - "kind": "def", - "end_line": 1261, - "ast_sha": "780d1925dc565162048293854a3c372f353a6afa3996238fb802f11679d8f0fd", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "46e92378291e04e1e7aa3d4b23ef56be1db317ab1c4c41802e2de3b05df5b40b", - "start_line": 1255, - "name": "send_download", - "arity": 3 - }, - "put_new_layout/2:743": { - "line": 743, - "guard": "(is_tuple(layout) and tuple_size(layout) == 2) or is_list(layout) or layout == false", - "pattern": "%Plug.Conn{state: state} = conn, layout", - "kind": "def", - "end_line": 756, - "ast_sha": "7bfe23c8d97019c2d24b271473d2f955dc378a08ea7bb038b2b94f49f2acc958", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "085c55c6e4ea31a46e57d2e0883b3fa4baf36862272a5c2d69ed90c510f755b1", - "start_line": 743, - "name": "put_new_layout", - "arity": 2 - }, - "get_flash/1:1723": { - "line": 1723, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 1725, - "ast_sha": "7e1585bf8de826c394c785dd34835dc980be75f3b0658ad9c2bfca83b3a598e7", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "8b8e328bc1f714eb0eae8a6aabc374a03c4287d3744e5ccfa86c4797e90d6313", - "start_line": 1723, - "name": "get_flash", - "arity": 1 - }, - "validate_local_url/1:510": { - "line": 510, - "guard": null, - "pattern": "<<\"/\"::binary, _::binary>> = to", - "kind": "defp", - "end_line": 514, - "ast_sha": "9303b9158bf586587017ba6019b19dcf498abbcf07b28bf2458219cad3a4979b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9c4cf5293f8a665c55d9d8dbe080a5b8808c6a30dc6cfbf09831f0cfc2e1819d", - "start_line": 510, - "name": "validate_local_url", - "arity": 1 - }, - "put_private_layout/4:705": { - "line": 705, - "guard": null, - "pattern": "conn, private_key, kind, no_format", - "kind": "defp", - "end_line": 729, - "ast_sha": "6a12556bd9f9161a36ca801ee61a807eab7f73650a7a77ff6db2cf33227b7b19", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9b5ad659fe46e818a53bb1558ad789895d2c8fcbe5f0433abcda59d2bebdc57a", - "start_line": 705, - "name": "put_private_layout", - "arity": 4 - }, - "put_router_url/2:1131": { - "line": 1131, - "guard": null, - "pattern": "conn, %URI{} = uri", - "kind": "def", - "end_line": 1132, - "ast_sha": "2ca9110b64832227f9e15990032d5a3695818a23d4db5d1f17f2aee82513c049", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "d8312a8dbcb335941c30566c92ca9395028d8899d820cc9e0e07bba101629a02", - "start_line": 1131, - "name": "put_router_url", - "arity": 2 - }, - "prepare_assigns/4:1019": { - "line": 1019, - "guard": null, - "pattern": "conn, assigns, template, format", - "kind": "defp", - "end_line": 1034, - "ast_sha": "4f36d9506eabe28e09bb459a9e89d45fca1049f5cfd5a926f805a82615a98b5e", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9190f5748d2cf450e649844d719a1f69ad5cd5f9e49b268f117bd52a6bd1abf3", - "start_line": 1019, - "name": "prepare_assigns", - "arity": 4 - }, - "send_download/2:1243": { - "line": 1243, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 1243, - "ast_sha": "b1a216bf51ba7a321bc7db7a919d4c76223e3f3675135ffaa8ded80f479229ce", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "8f3ae5dd86b69ba3218b03927e3b3f3d22ea5ce57e64d801c44474995c00f3c8", - "start_line": 1243, - "name": "send_download", - "arity": 2 - }, - "send_resp/4:1094": { - "line": 1094, - "guard": null, - "pattern": "conn, default_status, default_content_type, body", - "kind": "defp", - "end_line": 1097, - "ast_sha": "bf0dd88f3528c82d3ce824b53182e9a80bfd8146aa1259344ab2e9e3196392e4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "61a29dba3b3e676850325ce3a9d1c18b9838c3786ed13837a09e5a2654c0b6f1", - "start_line": 1094, - "name": "send_resp", - "arity": 4 - }, - "parse_exts/2:1602": { - "line": 1602, - "guard": null, - "pattern": "type, \"*\"", - "kind": "defp", - "end_line": 1602, - "ast_sha": "967965b94682ab69fc94a42b454418eb7b9707070ed2a20728137be8fe3c58c8", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fe02498fd8c7396e9ef11ede3a008ad8e20d356f304cc8830971df4b7764d8ed", - "start_line": 1602, - "name": "parse_exts", - "arity": 2 - }, - "get_format/1:1174": { - "line": 1174, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 1175, - "ast_sha": "762211201eb2ac1b26110e839ee21d8fca4fc0501ea62f622b03ed031d427ec7", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "befab57236d675b960013203077dcd29419f6d40914f7b0514300d0482b0028c", - "start_line": 1174, - "name": "get_format", - "arity": 1 - }, - "assigns_layout/3:1040": { - "line": 1040, - "guard": null, - "pattern": "conn, _assigns, format", - "kind": "defp", - "end_line": 1070, - "ast_sha": "f5cb6ca222131c3a787118274b5467abad65154f7172b19249d1be63a221050c", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "0c5986028a56b15f71cf295241aa328322a20fcad180b85d6d2aa99bec8992b3", - "start_line": 1040, - "name": "assigns_layout", - "arity": 3 - }, - "put_view/2:540": { - "line": 540, - "guard": null, - "pattern": "%Plug.Conn{} = conn, module", - "kind": "def", - "end_line": 547, - "ast_sha": "52d40ce5fd0ddf5086460ad799ac3146273794581fd5fff82f23dec990fd3f44", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "70d7f8f296056088afb713b36ebc091ca2a279c6c3d9abcd76dcdec0b2d6928f", - "start_line": 540, - "name": "put_view", - "arity": 2 - }, - "url/1:499": { - "line": 499, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 503, - "ast_sha": "8145d86afcc0fe0139a1375e0c5b688ecf5284b5c5cb0a1782d9e6f5e0c4646d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e3ae9e1697f2e7d023a4a9be49572bb92f2f6545cf6cdb37fd43baa378c79a5e", - "start_line": 499, - "name": "url", - "arity": 1 - }, - "view_template/1:347": { - "line": 347, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 348, - "ast_sha": "b8a6d8bba8f38c035747bb2df892adce2d8edce1b61a21804d6219c41fb6179e", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "5416f38872b9d43e68197561c5ecf736d00318dfdd7b4d2282ce8d15b80662f1", - "start_line": 347, - "name": "view_template", - "arity": 1 - }, - "controller_module/1:328": { - "line": 328, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 328, - "ast_sha": "1997b6cfe6a8ae1707e49c74ca90e07118176c745340071a9b2ccb66a3a591cc", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "4b6f14a7018ce41a33d10435a610b6e003b1825c7c2442dbe24f169d5895e852", - "start_line": 328, - "name": "controller_module", - "arity": 1 - }, - "status_message_from_template/1:1754": { - "line": 1754, - "guard": null, - "pattern": "template", - "kind": "def", - "end_line": 1761, - "ast_sha": "e507db1f56229aed49f35d4719c4567640e08c74957c46c26c52318e7df2fc71", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "6d8da504d53dae4f0ca4191cb504fc0ad8e15d3282ccca6682bba4fc1f44b5d4", - "start_line": 1754, - "name": "status_message_from_template", - "arity": 1 - }, - "accepts/2:1521": { - "line": 1521, - "guard": null, - "pattern": "conn, [_ | _] = accepted", - "kind": "def", - "end_line": 1527, - "ast_sha": "ce65a68b3815c663c41c1b3591bdb7fc7f77d7f133b9148480902b384ce1d581", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "469b3dd19d6def8e6e7edf0644b5f7f518d57f936898cada4765038f443d4976", - "start_line": 1521, - "name": "accepts", - "arity": 2 - }, - "scrub_param/1:1345": { - "line": 1345, - "guard": "is_atom(mod)", - "pattern": "%{__struct__: mod} = struct", - "kind": "defp", - "end_line": 1346, - "ast_sha": "3c96f428805c576ced518e7c69493c9027665fd62e3be5fa00015221f9b3d03e", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "cc55bdd6d83af45f1386ede861553b01a7a1f04efa30cb183091c96aef67b75c", - "start_line": 1345, - "name": "scrub_param", - "arity": 1 - }, - "send_download/3:1245": { - "line": 1245, - "guard": null, - "pattern": "conn, {:file, path}, opts", - "kind": "def", - "end_line": 1252, - "ast_sha": "ff086f7536843e6578747380a255434493f030a65ba3482f8a57c67b69e45106", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e4e5f5f8a94040a3b2ed63282a86de3c7b86d103ebcf6deccb7108966d83d434", - "start_line": 1245, - "name": "send_download", - "arity": 3 - }, - "parse_header_accept/4:1558": { - "line": 1558, - "guard": null, - "pattern": "conn, [h | t], acc, accepted", - "kind": "defp", - "end_line": 1571, - "ast_sha": "af5a604ca310c09ee08116949e0d3ee1267b6160bbee8c6c7751a6fe034b7e37", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "4725f18268e80c50c5a9f05a200f749d033ff6d79b0e3701321910d7314530f6", - "start_line": 1558, - "name": "parse_header_accept", - "arity": 4 - }, - "view_module/2:603": { - "line": 603, - "guard": null, - "pattern": "conn, format", - "kind": "def", - "end_line": 616, - "ast_sha": "feeed6ad7c48f85a388df04ae4a1700a3588528d94e2b49dc97dae68347c4075", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fcafec71384bb5901a55529d27e20b9b6de8e6a6a74fd2e7fc2321c95cdd73d0", - "start_line": 603, - "name": "view_module", - "arity": 2 - }, - "get_disposition_type/1:1290": { - "line": 1290, - "guard": null, - "pattern": "other", - "kind": "defp", - "end_line": 1294, - "ast_sha": "465b4e3af0fb0a6eed1b1c8dda8a89124643f5cb093a81c29630e8e0477119a4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e2fb12616796915846c1e9a38832c5e8493995f45de69007bc501f6e51197b89", - "start_line": 1290, - "name": "get_disposition_type", - "arity": 1 - }, - "scrub?/1:1363": { - "line": 1363, - "guard": null, - "pattern": "<<\" \"::binary, rest::binary>>", - "kind": "defp", - "end_line": 1363, - "ast_sha": "44187f34f742ddb4b7e76b404990334c19775f6063d5f2a913f4f615ba82eb2f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "77fcdbea1564eb9596cb6e55beddbcb33e1490bc5590093c62c6046188f3f7be", - "start_line": 1363, - "name": "scrub?", - "arity": 1 - }, - "json_response?/1:417": { - "line": 417, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 421, - "ast_sha": "262906d4d62539aeadcc1a5cf47fe1500d10c4d2c8ec8bc4a8c1ad84c47850e5", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "304b962e4ed09b1e663ff67115e26461112159f9911939754dba3a7e6e5d49cf", - "start_line": 417, - "name": "json_response?", - "arity": 1 - }, - "render/2:872": { - "line": 872, - "guard": "is_binary(template) or is_atom(template)", - "pattern": "conn, template", - "kind": "def", - "end_line": 873, - "ast_sha": "ccb5744a99ce3e0a6039ea84779249b9f768c2d15efe6b1ff0027e95271ce755", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "490fbad4c87f9c40a033735cf15cf7cf45831c92f0eb2101a48a1b86ca458edf", - "start_line": 872, - "name": "render", - "arity": 2 - }, - "prepare_send_download/3:1264": { - "line": 1264, - "guard": null, - "pattern": "conn, filename, opts", - "kind": "defp", - "end_line": 1281, - "ast_sha": "f3998c36e0937e176f16d48482ca48a0bc47e16ccc5ed323e24f6913243e674a", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "0521ce242b156847430264d6d3af6dd42239faf9d655f1f7800feecc36f0a3ce", - "start_line": 1264, - "name": "prepare_send_download", - "arity": 3 - }, - "put_static_url/2:1150": { - "line": 1150, - "guard": "is_binary(url)", - "pattern": "conn, url", - "kind": "def", - "end_line": 1151, - "ast_sha": "94782649cf09a7ceafa65dabc76e5bf57ff174b7451cad7a9432870378eea93c", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "7bdc8491453602d751a72f2686841d66102754caa75d9fc51bd4280df8b2e654", - "start_line": 1150, - "name": "put_static_url", - "arity": 2 - }, - "validate_jsonp_callback!/1:439": { - "line": 439, - "guard": null, - "pattern": "<<>>", - "kind": "defp", - "end_line": 439, - "ast_sha": "6b2887dfe346231ae6007d22fc02dcec5aec7b6b4cc023ada14fbf5d49bcec4f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "83b18aa6913df34d6699b18b594b7e7f58d21bc94040270cd5cc1260e9538d71", - "start_line": 439, - "name": "validate_jsonp_callback!", - "arity": 1 - }, - "scrub_params/2:1334": { - "line": 1334, - "guard": "is_binary(required_key)", - "pattern": "%Plug.Conn{} = conn, required_key", - "kind": "def", - "end_line": 1342, - "ast_sha": "43d683234d8780db6fdbc63df1fccddfdc45e63c4a099ee7aa771393525d6eb4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "89cfbe4b8aa66f9ecc1adc040f0eb1c2b8ea0261f607e44cf6b2410d4e3e7ff2", - "start_line": 1334, - "name": "scrub_params", - "arity": 2 - }, - "put_format/2:1164": { - "line": 1164, - "guard": null, - "pattern": "conn, format", - "kind": "def", - "end_line": 1164, - "ast_sha": "d1a635e6cac22bb92524d47f32121ccd5587bc0be0d3628d41d3800a3aa69ae0", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2d144a7f21246f21bf02a7440e43702544810a4f314c28ae31501109efac2857", - "start_line": 1164, - "name": "put_format", - "arity": 2 - }, - "scrub?/1:1365": { - "line": 1365, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 1365, - "ast_sha": "2763a3b03612efd2e097027cccbeeda1985f09b99f38f4ccb9b7201c73c48ea6", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "df23cb95ef9df066e43cad816d28eb69049316cb7df7b8758c85f5f2c093fd8e", - "start_line": 1365, - "name": "scrub?", - "arity": 1 - }, - "put_private_view/4:551": { - "line": 551, - "guard": "is_list(formats)", - "pattern": "conn, priv_key, kind, formats", - "kind": "defp", - "end_line": 553, - "ast_sha": "b9dd392ad21e1ec4cbe739f9498e7908fccd9c4d2005df2e192f2577d88a66a0", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "998156844dd31351432d6777f790d21837cb8cf3dfc06913c6c0c3236d3ae989", - "start_line": 551, - "name": "put_private_view", - "arity": 4 - }, - "get_disposition_type/1:1287": { - "line": 1287, - "guard": null, - "pattern": ":attachment", - "kind": "defp", - "end_line": 1287, - "ast_sha": "3cbfebabfeced6fd6bcea76a938231a742f32fe800e5c989998ee41c4e6e5bd4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "16e4cb2b2ee73980450b93787e5f48841f0e8ea77c3470cee9bde0304f7f3f7e", - "start_line": 1287, - "name": "get_disposition_type", - "arity": 1 - }, - "render_with_layouts/4:988": { - "line": 988, - "guard": null, - "pattern": "conn, view, template, format", - "kind": "defp", - "end_line": 999, - "ast_sha": "9e85024310c0948d12be965eb0247a35cf546a2a775a2789af9d4236615b198f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2e4ecd22dcf4b26f95cb05bcf1f4165a5bb1cfd9061f4ca60229a6824899d3d5", - "start_line": 988, - "name": "render_with_layouts", - "arity": 4 - }, - "action_fallback/1:314": { - "line": 314, - "guard": null, - "pattern": "plug", - "kind": "defmacro", - "end_line": 315, - "ast_sha": "a4a0b60eb8e61c25c096199bcc3b2cc06e04cad25698668ec76a71d291cd2346", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "619a8d8ab7f599c2134a21099ae7e6c065e0b7dc9d6b4eccae72736cfd776c85", - "start_line": 314, - "name": "action_fallback", - "arity": 1 - }, - "find_format/2:1606": { - "line": 1606, - "guard": "is_list(exts)", - "pattern": "exts, accepted", - "kind": "defp", - "end_line": 1606, - "ast_sha": "250f6e7edbf9be94262eaf262241716c96de9cf74fdbd6e416372aa37b0ee2aa", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "3eb9018739ffb8f091e84e5929b6f71cb2547b63efefdac065a99f4ca0d0e458", - "start_line": 1606, - "name": "find_format", - "arity": 2 - }, - "put_layout/2:650": { - "line": 650, - "guard": null, - "pattern": "%Plug.Conn{state: state} = conn, layout", - "kind": "def", - "end_line": 660, - "ast_sha": "628f2daca7c9fe30a6e11e0d8ce9ff4c2eef78f0e7c7e2bc402d03f67b1b3c7d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e191c8c2309560b2c9b073f1cf010105de947cbb0395130dd1c199cc33b4f8a0", - "start_line": 650, - "name": "put_layout", - "arity": 2 - }, - "template_render/4:1003": { - "line": 1003, - "guard": null, - "pattern": "view, template, format, assigns", - "kind": "defp", - "end_line": 1007, - "ast_sha": "5180602446f288e4ffece0cde935ed11a85e12c5c5327026e6688de158a8f1a3", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "597ebb366c031e88b6ee8255cba67c4d93936127d25462d7c16bc2813be0d793", - "start_line": 1003, - "name": "template_render", - "arity": 4 - }, - "to_map/1:1075": { - "line": 1075, - "guard": "is_map(assigns)", - "pattern": "assigns", - "kind": "defp", - "end_line": 1075, - "ast_sha": "9057b63c0142b7ef59737478055b3b9a77fb535a6cf8975a9c2950766327b31b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "83a271ead9f120c9b640f5212110fd5f0fe109d647f494741e8b668f4937461e", - "start_line": 1075, - "name": "to_map", - "arity": 1 - }, - "validate_jsonp_callback!/1:441": { - "line": 441, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 442, - "ast_sha": "b200b6b6aead937fc213b7c47ef4a7c3111d2956a08c76ab5a5f7cbd95749cc2", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "bb1c5d3cc376330c404f46f4bb6cc85e72eece059b915e76c4c5bb2719451a88", - "start_line": 441, - "name": "validate_jsonp_callback!", - "arity": 1 - }, - "fetch_flash/1:1643": { - "line": 1643, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 1643, - "ast_sha": "62a94c8c1075116df5f0f6cd7f81df4071c7a68a286eeeae1b5f59584cf97424", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "ae32afd06e04afa41f9ef6f35112bb5538f2f16f100b231deb37458f24a9b90d", - "start_line": 1643, - "name": "fetch_flash", - "arity": 1 - }, - "render/2:876": { - "line": 876, - "guard": null, - "pattern": "conn, assigns", - "kind": "def", - "end_line": 877, - "ast_sha": "75bffeac579a30d8f5eabb8de7cc04593c3352a1ab0a33a0d6e65127e2add4e4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "acfa45daec8ad7bd6a148997f4370b0dac95f52587733c031eea33c7a5a9dbba", - "start_line": 876, - "name": "render", - "arity": 2 - }, - "merge_flash/2:1680": { - "line": 1680, - "guard": null, - "pattern": "conn, enumerable", - "kind": "def", - "end_line": 1682, - "ast_sha": "0075f7a2db9572637c813c5b61866fbc741491471b2b70e239c75318b6b38050", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fd37cf59e3c9455fac8e7190c260b6cf1e66792f81fd5bd85065823ba624f3d7", - "start_line": 1680, - "name": "merge_flash", - "arity": 2 - }, - "protect_from_forgery/2:1376": { - "line": 1376, - "guard": null, - "pattern": "conn, opts", - "kind": "def", - "end_line": 1377, - "ast_sha": "12550dd67d55640891eeeb9994131d22304718481be8a23a9dee285bdd1dbba8", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "957508a679449c3569633812bc43de0281fb6c0fb0b585eb19650a8c7f99c410", - "start_line": 1376, - "name": "protect_from_forgery", - "arity": 2 - }, - "get_safe_format/1:1178": { - "line": 1178, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 1182, - "ast_sha": "cac3e57f51be5ae07219b93f639f10fc2f9ced8f9bc22cc5c99232af286f4bd7", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "41ade671c952dd9efa12257750486117aeb42038759fbdef4dc111040d1ff5d4", - "start_line": 1178, - "name": "get_safe_format", - "arity": 1 - }, - "view_module/1:603": { - "line": 603, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 603, - "ast_sha": "64fa8b371bb0c7032a1c0e06d7c4dd8d809ef74df93bd546609010ef9692339b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2517fc2ca6ef26c2535d1e4fc51f42c00b26a34c2f90a29d36cef36b309abc0e", - "start_line": 603, - "name": "view_module", - "arity": 1 - }, - "html/2:468": { - "line": 468, - "guard": null, - "pattern": "conn, data", - "kind": "def", - "end_line": 469, - "ast_sha": "ad1a23a4a8294ad198dd56563c69c4bd832107c756cafd93a3fd13b810a8b00f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2d474e3edb5b58ee5832fad34a00bbd143eb9b23ccac5640d5b75ac2403c724b", - "start_line": 468, - "name": "html", - "arity": 2 - }, - "find_format/2:1607": { - "line": 1607, - "guard": null, - "pattern": "_type_range, []", - "kind": "defp", - "end_line": 1607, - "ast_sha": "53add9fe63364ca116c0eefec419000c6e08a35c18699990fce50c7f2555ee1d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "cbc0a81a4aaa69ca7a41255bdc4af9f1d943dd3a6f819d5c6946fad3f5dd27f3", - "start_line": 1607, - "name": "find_format", - "arity": 2 - }, - "handle_header_accept/3:1550": { - "line": 1550, - "guard": null, - "pattern": "conn, [header | _], accepted", - "kind": "defp", - "end_line": 1554, - "ast_sha": "9c4f9decfb17ddd26eb8a4aa43f0aa7057de4bcf1fad010ab7ba7fe178f8429a", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "45f8afac1b548d2f1d22bd39f56fe97c2f6be4f3cab54d1ddd53699711415686", - "start_line": 1550, - "name": "handle_header_accept", - "arity": 3 - }, - "current_path/2:1822": { - "line": 1822, - "guard": "params == %{}", - "pattern": "%Plug.Conn{} = conn, params", - "kind": "def", - "end_line": 1823, - "ast_sha": "21a4bb88ffd66e7e0ffc57aacb60f7211fcd6071bbd7f3563339d4b7a072f3ed", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e2892e6002e27cc61e09eea41a8fac7b5350c5c50979a2bb706a2ca87740b41d", - "start_line": 1822, - "name": "current_path", - "arity": 2 - }, - "redirect/2:489": { - "line": 489, - "guard": "is_list(opts)", - "pattern": "conn, opts", - "kind": "def", - "end_line": 496, - "ast_sha": "874a70e2e6549ac003fb2a257f98ad7ca3fbe7eb051c101fa573f94a746e28cf", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "854f06197e97e431abd7fd92115489b8928d59cf388a3386d8418821ea45c525", - "start_line": 489, - "name": "redirect", - "arity": 2 - }, - "get_disposition_type/1:1288": { - "line": 1288, - "guard": null, - "pattern": ":inline", - "kind": "defp", - "end_line": 1288, - "ast_sha": "d3aeae7d7632d52596e863cf9c760dca4e95f46b99449b82d5d5c4a1095503a5", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a8fc634bf398d106c2a5161b6fe1cd1c42c0ffe999851ba6965a3d8926c73480", - "start_line": 1288, - "name": "get_disposition_type", - "arity": 1 - }, - "to_map/1:1076": { - "line": 1076, - "guard": "is_list(assigns)", - "pattern": "assigns", - "kind": "defp", - "end_line": 1076, - "ast_sha": "74bd6e6e2b2ab2e70f8ce68e65c51ca532e96ec9019619feb7e76d47c65500a8", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9afa93dc3d37d31e7a1ef9f3efb9e708c0db448e1368cd7cae5d9e83600b07fc", - "start_line": 1076, - "name": "to_map", - "arity": 1 - }, - "put_new_view/2:586": { - "line": 586, - "guard": null, - "pattern": "%Plug.Conn{} = conn, module", - "kind": "def", - "end_line": 593, - "ast_sha": "ccc653c5507a4305e46f4ac99173601070dd32007f1362388d2212e53b3f622e", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fa14a991d268c5b4b717d0b31f135443bc5457c6ed0f6f7c036a34ab92af1a51", - "start_line": 586, - "name": "put_new_view", - "arity": 2 - }, - "find_format/2:1609": { - "line": 1609, - "guard": null, - "pattern": "type_range, [h | t]", - "kind": "defp", - "end_line": 1614, - "ast_sha": "01a0f14574078e94a64a30725e43950573ea7a181dd48248141b6fe315531b9f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "aefb1cb0ea0ce3d215711d2e2d2dbc3302f3be7d240b3306b75156237a1e7031", - "start_line": 1609, - "name": "find_format", - "arity": 2 - }, - "flash_key/1:1771": { - "line": 1771, - "guard": "is_binary(binary)", - "pattern": "binary", - "kind": "defp", - "end_line": 1771, - "ast_sha": "db055723bd00d07de072c4bdfb3d4b5dbbc2b119ff5e00d3057446c081ad56fe", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "1466e47c43ddeec358f7fb2a2c1f4b79ce1fc6ceddccc1cac12cfc5b66bcf5a4", - "start_line": 1771, - "name": "flash_key", - "arity": 1 - }, - "put_layout_formats/2:810": { - "line": 810, - "guard": "(=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)) and\n is_list(formats)", - "pattern": "%Plug.Conn{state: state} = conn, formats", - "kind": "def", - "end_line": 812, - "ast_sha": "9dc51f64ef8b14d9bfff2346af0512c74d81a97201be758cd5a21e427cdcf4f6", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "16a6890b4cc432c71daed1730d4a77180c2db49a0a0c7d010036b628fc290297", - "start_line": 810, - "name": "put_layout_formats", - "arity": 2 - }, - "current_path/1:1794": { - "line": 1794, - "guard": null, - "pattern": "%Plug.Conn{query_string: query_string} = conn", - "kind": "def", - "end_line": 1795, - "ast_sha": "b9c9befc869019ed0bb55e65223a9b1696a33746dd1e59cc7ea18ce1d8c5e365", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fa6f683447039dbe4cf8804e528a72e229b4cbb5973ef1d90c3698d44374ce5c", - "start_line": 1794, - "name": "current_path", - "arity": 1 - }, - "put_layout_formats/2:815": { - "line": 815, - "guard": null, - "pattern": "%Plug.Conn{} = conn, _formats", - "kind": "def", - "end_line": 821, - "ast_sha": "ca22641220017cc6897de57eab84598f8ab0f937196945ee6dcaecafd33962c9", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9020dd293866ec1cf579cdaa7b5ffd4ecec085100f547e83287fd10de6aa6601", - "start_line": 815, - "name": "put_layout_formats", - "arity": 2 - }, - "template_render_to_iodata/4:1011": { - "line": 1011, - "guard": null, - "pattern": "view, template, format, assigns", - "kind": "defp", - "end_line": 1015, - "ast_sha": "c3a094e44ee4119df485ca99035d34cc92f5797ff7b4cc5b6d3bc78a56120486", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "62d5afb628a7ce6d6be67f1bb27977f3c5b6dcad8cf871574a2ef3b0279c7b56", - "start_line": 1011, - "name": "template_render_to_iodata", - "arity": 4 - }, - "refuse/3:1619": { - "line": 1619, - "guard": null, - "pattern": "_conn, given, accepted", - "kind": "defp", - "end_line": 1627, - "ast_sha": "4b077b6024042e453de82bacd80d1f0dfbba347491fb2d1db8c8ff12a5f19f51", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "3fdd04294a7784fa88b43ee5f398dfef6e86daf181977162ec1c3220669fec3e", - "start_line": 1619, - "name": "refuse", - "arity": 3 - }, - "assign/2:1911": { - "line": 1911, - "guard": "is_function(fun, 1)", - "pattern": "conn, fun", - "kind": "def", - "end_line": 1912, - "ast_sha": "0450746cc002d1f5f1925d618bbdcf42d065e2542525b0e482d04c304eca45cd", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "d22b37b3cfa7c96647070dd962f048e007266db2126298e4e0c7bc81e9845612", - "start_line": 1911, - "name": "assign", - "arity": 2 - }, - "find_format/2:1605": { - "line": 1605, - "guard": null, - "pattern": "\"*/*\", accepted", - "kind": "defp", - "end_line": 1605, - "ast_sha": "64a41935f028d3137f6185e233a9cd9ba92fe5e1d4f2a763b45c123e77d89ecf", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "20df83462bf3808f1b60364d3eeb26ead339760856a01d847e435281c31c1c8a", - "start_line": 1605, - "name": "find_format", - "arity": 2 - }, - "render/4:971": { - "line": 971, - "guard": "is_atom(view) and (is_binary(template) or is_atom(template))", - "pattern": "conn, view, template, assigns", - "kind": "def", - "end_line": 975, - "ast_sha": "9fc42543c7a285b210ce654ce4363fd4bd9dbedfd39b80b8534e5ff8c5976e59", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "5ad8b8b264791462043c229a6307fadb31fe27b8923c0f9f38f97fa19960e5eb", - "start_line": 971, - "name": "render", - "arity": 4 - }, - "get_flash/2:1739": { - "line": 1739, - "guard": null, - "pattern": "conn, key", - "kind": "def", - "end_line": 1740, - "ast_sha": "ba6a2680f2cc5935c99205a3884f2a681889f3d0392221c5168b1bb3e4b2e9f9", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9ae81ea98ff9d6d1d3952f5904fc889f6674601bd9016cd86f2c1c65bd6de1ad", - "start_line": 1739, - "name": "get_flash", - "arity": 2 - }, - "root_layout/2:848": { - "line": 848, - "guard": null, - "pattern": "conn, format", - "kind": "def", - "end_line": 849, - "ast_sha": "043cc56089c458a0a55d08c6eafae7aed7125c013a0aac0c8fe562391d3e9a9b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "7d7775d22db4f6b9673391ea77a9e23930a029d05062a4bbdc3e560391bdddf1", - "start_line": 848, - "name": "root_layout", - "arity": 2 - }, - "parse_header_accept/3:1582": { - "line": 1582, - "guard": null, - "pattern": "conn, {_, _, exts}, accepted", - "kind": "defp", - "end_line": 1584, - "ast_sha": "2e4533834fa868cee0038ca71de2d9594deb0d90839665c3259b559637cabc81", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "62dca9b44490bc9f88579a140664df7906b881b26c356b561996a327d58b0058", - "start_line": 1582, - "name": "parse_header_accept", - "arity": 3 - }, - "raise_invalid_url/1:521": { - "line": 521, - "guard": null, - "pattern": "url", - "kind": "defp", - "end_line": 522, - "ast_sha": "1ff503875f8d3ed00201b798240b73006c1e34235c5c2271a56d3bc969ef096c", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "df1aba13b8337c1d617079ecfd70e140e7370adbabe3786217e9edc77cc8d94e", - "start_line": 521, - "name": "raise_invalid_url", - "arity": 1 - }, - "assigns_layout/3:1038": { - "line": 1038, - "guard": null, - "pattern": "_conn, %{layout: layout}, _format", - "kind": "defp", - "end_line": 1038, - "ast_sha": "54fc6a4fed446ab5cebdf09288c66512292c9a2ca1f0184be1bc6bfb7ed70c7d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "0e36f1177e07650cbbbcd17ff5c18f613f72ec1277fd8e30d6465a11756a7786", - "start_line": 1038, - "name": "assigns_layout", - "arity": 3 - }, - "current_url/2:1888": { - "line": 1888, - "guard": null, - "pattern": "%Plug.Conn{} = conn, %{} = params", - "kind": "def", - "end_line": 1889, - "ast_sha": "774caa3821cc1eebaf9d6f68e0b9703f70ee62a8662b0644d76f90d2cab6cf6f", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "16911b13ffc813228d0306d06966ac6060c7ed43dbb96160e35baf885d946e03", - "start_line": 1888, - "name": "current_url", - "arity": 2 - }, - "get_csrf_token/0:1440": { - "line": 1440, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 1440, - "ast_sha": "a1a7fbdee1275ae66c037393cab82aab4821740d0113fc8b0e081f1b3c6eca70", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "6d6ee0bf92f87e6896dcac0ced69c4df9b2daa5f0b2bd42ce0b0255fe1041615", - "start_line": 1440, - "name": "get_csrf_token", - "arity": 0 - }, - "__plugs__/2:1918": { - "line": 1918, - "guard": null, - "pattern": "controller_module, opts", - "kind": "def", - "end_line": 2006, - "ast_sha": "7f18430969dba92fb60b0d801faac66db06eb769f72c6e961fbf23baace47ad7", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "c4ed0e03037a322988efef4f2efc8b7f0c9880c8dce2491cdc4d475b831d6216", - "start_line": 1918, - "name": "__plugs__", - "arity": 2 - }, - "parse_exts/2:1601": { - "line": 1601, - "guard": null, - "pattern": "\"*\", \"*\"", - "kind": "defp", - "end_line": 1601, - "ast_sha": "1d236c42986020810311cc0996f2570a0a60287e5dccd1c14cc767deda1e96a5", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "bc500016da3ce6f2f09e89235d998fcdd68c2959e331ab211a594cbb66b03fa2", - "start_line": 1601, - "name": "parse_exts", - "arity": 2 - }, - "put_new_view/2:582": { - "line": 582, - "guard": "=:=(state, :unset) or =:=(state, :set) or =:=(state, :set_chunked) or =:=(state, :set_file)", - "pattern": "%Plug.Conn{state: state} = conn, formats", - "kind": "def", - "end_line": 583, - "ast_sha": "33b4d5d68b5f0d8d09e9f287ca7b63aad21a943a7b9786edd7c678b397ae71ae", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9eed9dffa6eaa7409f4159f24916800493eb4ebeb9ac17fbd602901c30071cc6", - "start_line": 582, - "name": "put_new_view", - "arity": 2 - }, - "router_module/1:334": { - "line": 334, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 334, - "ast_sha": "b108d19169945a012245a7d4a9a1ce8c55eb2dbf58dda53837cec515fc72c151", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "64f2a3e0fbb1b2a1d46523d568ff5b72e80f681a49aca1b6ea87fc921a532026", - "start_line": 334, - "name": "router_module", - "arity": 1 - }, - "json/2:363": { - "line": 363, - "guard": null, - "pattern": "conn, data", - "kind": "def", - "end_line": 365, - "ast_sha": "f2a9ab311c7e12daa45c199f536b106b09236a6a16f5b3306b4d18242ab5b1e6", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "95f600480e5cdd2bd8892de9c268053de9e67a43ca63654d9084626022990ed8", - "start_line": 363, - "name": "json", - "arity": 2 - }, - "layout_formats/1:828": { - "line": 828, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 829, - "ast_sha": "34a3eab29a74bc0ace9066f517ac36a8c887e9d6d8ff8b28a4085b8b54108328", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "de01ae3f4d48089cf794a05cbe1304bea1a80e8d8a84a098e7d34cff2ae10dd3", - "start_line": 828, - "name": "layout_formats", - "arity": 1 - }, - "current_url/1:1842": { - "line": 1842, - "guard": null, - "pattern": "%Plug.Conn{} = conn", - "kind": "def", - "end_line": 1843, - "ast_sha": "b6ed35bac47ea731d0efe4c0922be0052bf52900b31654477d77238f025efc1b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "b40729934cb68d1c4fa99b233feb5d5f98a42cf4e4c9125fead6d84f243ddce1", - "start_line": 1842, - "name": "current_url", - "arity": 1 - }, - "parse_q/1:1588": { - "line": 1588, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 1596, - "ast_sha": "06b7277a46e1d131391c9eea8fe8f71a32979644ec4a2b44ddddbe2e0decd73b", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "8335dee45bceaa8d90633e73e683bb58c358579bea22871e8a93e4759143d8df", - "start_line": 1588, - "name": "parse_q", - "arity": 1 - }, - "action_name/1:322": { - "line": 322, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 322, - "ast_sha": "8b23412bbe4fb3ce552886fbd1132a4a88e6b3958d7eb17bd21716a9ff8d5215", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fe8211d23c7f21a827f3adac476728ce9f183decc5fb6cc6dce62459f3c3caff", - "start_line": 322, - "name": "action_name", - "arity": 1 - }, - "render/3:954": { - "line": 954, - "guard": "is_binary(template) and (is_map(assigns) or is_list(assigns))", - "pattern": "conn, template, assigns", - "kind": "def", - "end_line": 957, - "ast_sha": "10d2359d6a5f0ada2dc62f5d252b741f71b1a33daffb4ff330775a9d65799311", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "b29618e6c633eee39c91b6ccf3ac63005391fbea08b479a67a61174a46ac2639", - "start_line": 954, - "name": "render", - "arity": 3 - }, - "fetch_flash/2:1643": { - "line": 1643, - "guard": null, - "pattern": "conn, _opts", - "kind": "def", - "end_line": 1662, - "ast_sha": "93049ec766b4e8e4388e152621805fc612bfde1179d6ceec681bd043a501d01c", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e1b81807b94ccce0c42341105fff2acbbed37d985d841d6a00f029ea878b9d4f", - "start_line": 1643, - "name": "fetch_flash", - "arity": 2 - }, - "handle_params_accept/3:1531": { - "line": 1531, - "guard": null, - "pattern": "conn, format, accepted", - "kind": "defp", - "end_line": 1537, - "ast_sha": "67b8685287402ba56eab0c92a5616c33001f63abb4f5f0e437a85a711753b01a", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "00d29248f468fc59e5d0e35fbb798ebf0685470a4a293f1146f79c3ae3edc9bb", - "start_line": 1531, - "name": "handle_params_accept", - "arity": 3 - }, - "allow_jsonp/2:392": { - "line": 392, - "guard": null, - "pattern": "conn, opts", - "kind": "def", - "end_line": 411, - "ast_sha": "501554872c5b067cec74deb99d29484bc96ce8e3c5c1d38d0a6a76e0f21bec71", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "c26330230de0e57cca75bcc3383cfe27fc070115f62ed31cdb4404ac61c9445e", - "start_line": 392, - "name": "allow_jsonp", - "arity": 2 - }, - "scrub_param/1:1349": { - "line": 1349, - "guard": null, - "pattern": "%{} = param", - "kind": "defp", - "end_line": 1351, - "ast_sha": "9fc916d2b6e401b624fe4803f16685cc7262478955ba1448a02c8b37ed915988", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "8ef7791d21ed6dc239ee9318cdd30602c8ba9f93cfd5bbe684ce386dd98cb261", - "start_line": 1349, - "name": "scrub_param", - "arity": 1 - }, - "render_and_send/4:978": { - "line": 978, - "guard": null, - "pattern": "conn, format, template, assigns", - "kind": "defp", - "end_line": 985, - "ast_sha": "bcfbc1015c80b816b04ee40c16146a36a2de13bb209b656699343cf6a1a2afdd", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "b2e5e533e4dfa894845bd05778dc56920916f2a88a1b55c3d78a18c569d6a2e4", - "start_line": 978, - "name": "render_and_send", - "arity": 4 - }, - "split_template/1:1078": { - "line": 1078, - "guard": "is_atom(name)", - "pattern": "name", - "kind": "defp", - "end_line": 1078, - "ast_sha": "f310164c9ee809042a3a2aeaf2fb4e4aaef2d7a3c96535894fac9973441326b9", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "7c89cfff58b2034e5d0fd4eae3dc2e60d24dc881a950ebf81dea5077fc9ac3f0", - "start_line": 1078, - "name": "split_template", - "arity": 1 - }, - "get_private_layout/3:852": { - "line": 852, - "guard": null, - "pattern": "conn, priv_key, format", - "kind": "defp", - "end_line": 859, - "ast_sha": "c22a705d35aab3f85c7f7b62d40d5f22111e50298cf4fe3c8fc4171dcbe4384a", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "749852ea6965d63375bf453b24442a1cdbceea6a204c64a09c300eb2f1c5d33a", - "start_line": 852, - "name": "get_private_layout", - "arity": 3 - }, - "split_template/1:1080": { - "line": 1080, - "guard": "is_binary(name)", - "pattern": "name", - "kind": "defp", - "end_line": 1090, - "ast_sha": "9546273babaf6a2c2439a7b12ba083d00d0ccaca027b68658678f89c4b4b71db", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a5a820b6f5962cf6de44c814c906f7894cdc427aa360007c6d40eb7fa2a887d8", - "start_line": 1080, - "name": "split_template", - "arity": 1 - }, - "scrub?/1:1364": { - "line": 1364, - "guard": null, - "pattern": "\"\"", - "kind": "defp", - "end_line": 1364, - "ast_sha": "a8b940b641a1f26e7b41952124e13431c09a121f8f1dc414348935a32772e6df", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "5743bdb0858926c2b9927c4ff8b1075fef0ee91de102441c9ce054952351a836", - "start_line": 1364, - "name": "scrub?", - "arity": 1 - }, - "render/3:944": { - "line": 944, - "guard": "is_atom(template) and (is_map(assigns) or is_list(assigns))", - "pattern": "conn, template, assigns", - "kind": "def", - "end_line": 951, - "ast_sha": "e2e5c8ee9a0e3fc4f91f484b36e8aeeec73d56d0b6783ab5fb4bfe956924e665", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "1baf1a07ef065a5c3b3184d2bfe6054876cf9c00ceec77979c75a2d3779ef47f", - "start_line": 944, - "name": "render", - "arity": 3 - }, - "put_private_layout/4:665": { - "line": 665, - "guard": "is_list(layouts)", - "pattern": "conn, private_key, kind, layouts", - "kind": "defp", - "end_line": 702, - "ast_sha": "25ee9f829287d84aee04f22fb5af89419655f77fb9e3ba49ed7aa6d28045c70d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "ad82167fa2cca0797e6a7609af8df8158a5125522a4edbb80db50d793f2fe9ab", - "start_line": 665, - "name": "put_private_layout", - "arity": 4 - }, - "warn_if_ajax/1:1304": { - "line": 1304, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 1307, - "ast_sha": "9b3a774797f3e030140e4855323d5ed5d6c1f0fa57e101709ee98ec84e670e30", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "7aede4044ea71629e3da2bf651a962b3ecbb7308acfe0218d46651118cec19e4", - "start_line": 1304, - "name": "warn_if_ajax", - "arity": 1 - }, - "protect_from_forgery/1:1376": { - "line": 1376, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 1376, - "ast_sha": "417fbdde22fb1de7711161c85f9608a0e65dfef6427c33986a7e839b79a80146", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e355e6e3289879e6d41be064a75f382446940394d5b0b37b429964ada502ccfc", - "start_line": 1376, - "name": "protect_from_forgery", - "arity": 1 - }, - "put_static_url/2:1146": { - "line": 1146, - "guard": null, - "pattern": "conn, %URI{} = uri", - "kind": "def", - "end_line": 1147, - "ast_sha": "5e5acd9962e1a5d3eb2ae45367468e5756075d5096afb8f255f3aa2cb0e336a0", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9ffb35a2b26cf5e3810bb888f6b73bb0e5cada3f47b95d009ad6133c527da1c1", - "start_line": 1146, - "name": "put_static_url", - "arity": 2 - }, - "encode_filename/2:1285": { - "line": 1285, - "guard": null, - "pattern": "filename, true", - "kind": "defp", - "end_line": 1285, - "ast_sha": "09946eb278030dc45dff80cef34c6dc5ae11318cf9bf8175bb947cd9f09aa6d6", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "45c48d200d4d05a3d81704596f38acaafd6819387d2d63273399dffa2ee1c178", - "start_line": 1285, - "name": "encode_filename", - "arity": 2 - }, - "validate_jsonp_callback!/1:435": { - "line": 435, - "guard": "(is_integer(h) and (h >= 48 and =<(h, 57))) or (is_integer(h) and (h >= 65 and =<(h, 90))) or\n (is_integer(h) and (h >= 97 and =<(h, 122))) or h == 95", - "pattern": "<>", - "kind": "defp", - "end_line": 437, - "ast_sha": "2af79ce5e79b7d0b358c539d75b50335c5f14930443f682f7fe8b9786c501862", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "679ab5f001ce3f2ada7d36e23f474f59a523860421fd25610e476d6ca0ccf42b", - "start_line": 435, - "name": "validate_jsonp_callback!", - "arity": 1 - }, - "put_secure_defaults/1:1415": { - "line": 1415, - "guard": null, - "pattern": "%Plug.Conn{resp_headers: resp_headers} = conn", - "kind": "defp", - "end_line": 1431, - "ast_sha": "4cb6f01cbf7a57ac4643a329a5d4eb9eecc86f331ef0094d800e9306e62db18e", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "84326d2cde55901fc650594df43a3e37888654e6da4e3efba04809118e1af669", - "start_line": 1415, - "name": "put_secure_defaults", - "arity": 1 - }, - "clear_flash/1:1767": { - "line": 1767, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 1768, - "ast_sha": "9a6447e24f3100a27412ac532d6ee9eb45bfd6dceb0e1ac63104287dd76e5ed3", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "e06a43fd7da899bda23854c0a5dbcd7e438f99256f23849b1487b5d9c1cd2a81", - "start_line": 1767, - "name": "clear_flash", - "arity": 1 - }, - "root_layout/1:848": { - "line": 848, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 848, - "ast_sha": "f0e298915f706b2db841db4eee57f176c8015eb34c686cf6ad09aabfe2bd2f44", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fe055d911eb383f4044c80b8397b7f06e95712ce59af61b11acf2de275e1438f", - "start_line": 848, - "name": "root_layout", - "arity": 1 - }, - "assign/2:1915": { - "line": 1915, - "guard": null, - "pattern": "conn, assigns", - "kind": "def", - "end_line": 1915, - "ast_sha": "d80740a85de19f53e6c0fb2e6a36cd06963e53aae273a4f8116b869057473aa8", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "c4d4abe697c077b6f689a8129731b1e91ff9544c057decd8a02c31c1cee098d6", - "start_line": 1915, - "name": "assign", - "arity": 2 - }, - "put_private_view/4:557": { - "line": 557, - "guard": null, - "pattern": "conn, priv_key, kind, value", - "kind": "defp", - "end_line": 558, - "ast_sha": "d8cdf7196d8cf11d341d9d2ca8fcf4d9c9d3adfe7727736f7a386049547f5655", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "c2efb3f8c3f09588a887e3270479c4fc82821a160aff56c861d3b67bec0ecbad", - "start_line": 557, - "name": "put_private_view", - "arity": 4 - }, - "parse_header_accept/4:1575": { - "line": 1575, - "guard": null, - "pattern": "conn, [], acc, accepted", - "kind": "defp", - "end_line": 1579, - "ast_sha": "1730969df8a8754d1307e28925cf868372d687bae286d736f02990e029379315", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "81efc7a674d5896a019878132f7c24b89e8087ff0c745d04d9d6a22885ef794b", - "start_line": 1575, - "name": "parse_header_accept", - "arity": 4 - }, - "scrub_param/1:1355": { - "line": 1355, - "guard": "is_list(param)", - "pattern": "param", - "kind": "defp", - "end_line": 1356, - "ast_sha": "116091221aeffd70973eb626560003fe7c2afd72213f3e1980cf4e4162e00829", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "6116772eb1667c7a2e30607cab464d1c4449db4dc0144bed0cd968b6d98b6256", - "start_line": 1355, - "name": "scrub_param", - "arity": 1 - }, - "layout/1:838": { - "line": 838, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 838, - "ast_sha": "a3c71077a2eb244a109914816be1a541dbc72722aa23fc3bbcb44b88b51dcbad", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "164f03a758176229ac8438ec9a6904443b39a3485976a3a8bb8a2055e7c1f265", - "start_line": 838, - "name": "layout", - "arity": 1 - }, - "jsonp_body/2:425": { - "line": 425, - "guard": null, - "pattern": "data, callback", - "kind": "defp", - "end_line": 432, - "ast_sha": "1e16585cc501930b69cb1963d37da016675b3e04364bd4cebc051d396871221c", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "078bfedc70590e970d1990965bee0837b3d2fa1ad860a60b264afd5e8013edc3", - "start_line": 425, - "name": "jsonp_body", - "arity": 2 - }, - "validate_local_url/1:508": { - "line": 508, - "guard": null, - "pattern": "<<\"//\"::binary, _::binary>> = to", - "kind": "defp", - "end_line": 508, - "ast_sha": "7e29bb2b68ac353e3f89b3dbaf2c950fb6e22e94cc20565ea8197716e51fffb4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9fbd871aae6f1e1f999284d43ea0acb86297a0304115bfddc868a5aa19f2a4fe", - "start_line": 508, - "name": "validate_local_url", - "arity": 1 - }, - "expand_alias/2:258": { - "line": 258, - "guard": null, - "pattern": "other, _env", - "kind": "defp", - "end_line": 258, - "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", - "start_line": 258, - "name": "expand_alias", - "arity": 2 - }, - "layout/2:838": { - "line": 838, - "guard": null, - "pattern": "conn, format", - "kind": "def", - "end_line": 839, - "ast_sha": "f8e993e63d29de6c2cc7401ec3450cacb04aec457a4d42a1716da111e5e18bea", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9d49d83d09014d4d78ea45fc9345c292c405407fb7d7b68078352a6f72bb55d4", - "start_line": 838, - "name": "layout", - "arity": 2 - }, - "normalized_request_path/1:1830": { - "line": 1830, - "guard": null, - "pattern": "%{path_info: info, script_name: script}", - "kind": "defp", - "end_line": 1831, - "ast_sha": "e139df2f484eeec25c17a1ca541f3673d0198d8d9ed1fce8e993105abe22afed", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "707fd7b61e16ec98bc567e0d39da4efe8f25b16ba353b4508f68a3ddcc468dd2", - "start_line": 1830, - "name": "normalized_request_path", - "arity": 1 - }, - "put_secure_browser_headers/1:1403": { - "line": 1403, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 1403, - "ast_sha": "c360cc9db029904f1ae80547d1b509f20702614cae0cf615e61959b83b4c07d4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a0d39e0d147aedd748e7fb3d9c09ec30f87e5faeaa9ed54cb8ca1d6c5e88728c", - "start_line": 1403, - "name": "put_secure_browser_headers", - "arity": 1 - }, - "current_path/1:1790": { - "line": 1790, - "guard": null, - "pattern": "%Plug.Conn{query_string: \"\"} = conn", - "kind": "def", - "end_line": 1791, - "ast_sha": "5809befb206b65265e217f4a0a47ac707c17f3d6920a784115c4f051d3a39914", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "9241488e97168c79c7254c9165e273d0764b71eae05b71e12d6cf6f8880a6625", - "start_line": 1790, - "name": "current_path", - "arity": 1 - }, - "current_path/2:1826": { - "line": 1826, - "guard": null, - "pattern": "%Plug.Conn{} = conn, params", - "kind": "def", - "end_line": 1827, - "ast_sha": "8cb27effecdcef6cd2e963eed61c8a78d3e5295b8ec23f09ad766785b3c4bfc4", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "eaaadf2226d57f139e2894a396b0f610e3ec40ad5b20f2a6842e36cc71bd0423", - "start_line": 1826, - "name": "current_path", - "arity": 2 - }, - "render/3:960": { - "line": 960, - "guard": "is_atom(view) and (is_binary(template) or is_atom(template))", - "pattern": "conn, view, template", - "kind": "def", - "end_line": 966, - "ast_sha": "70ddddbf2297085caa7ffe9c8207aa1f43c53f6f3e97685e28fd2bae0c6e2ccf", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "a4cd40557eeedc1640adaacc5bc9d4f2f37dc793aeff20e5187344757de24360", - "start_line": 960, - "name": "render", - "arity": 3 - }, - "flash_key/1:1772": { - "line": 1772, - "guard": "is_atom(atom)", - "pattern": "atom", - "kind": "defp", - "end_line": 1772, - "ast_sha": "2a7a1d0af29abd0bf4c4abdb618dd31ebc512f75a61fa7eb1544b56601a94bfc", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "ed19748fb1a427f6db29c8f5870d640716c8c01bf31c2fdf0958a0452dba31e4", - "start_line": 1772, - "name": "flash_key", - "arity": 1 - }, - "put_secure_browser_headers/2:1409": { - "line": 1409, - "guard": "is_map(headers)", - "pattern": "conn, headers", - "kind": "def", - "end_line": 1412, - "ast_sha": "6a36dcee1a3e5661bc6af3514901b52cb9d13c601df6143b0a0effafb506e033", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "7a10f35b5857c38324a00a2a370f5b5acda643d590c0972e319c3b2c0d3fb582", - "start_line": 1409, - "name": "put_secure_browser_headers", - "arity": 2 - }, - "scrub_param/1:1359": { - "line": 1359, - "guard": null, - "pattern": "param", - "kind": "defp", - "end_line": 1360, - "ast_sha": "cbc013d72090fcde2b878d861c7b7e95cf79e03d2b572058ca9f54527f248228", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "f3057a82f7804d4753ff3f48635515c7a1ed5f795075a16bc54db81cb880f0c1", - "start_line": 1359, - "name": "scrub_param", - "arity": 1 - }, - "encode_filename/2:1284": { - "line": 1284, - "guard": null, - "pattern": "filename, false", - "kind": "defp", - "end_line": 1284, - "ast_sha": "6720c0d36d9da3a53ae834a791b14d3c34b5b30049f619ee077c1f7edcc93502", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "fbdd4f1fb1b17a37faf3aa3936c97943f870cc82075683696c84406734926ce1", - "start_line": 1284, - "name": "encode_filename", - "arity": 2 - }, - "expand_alias/2:255": { - "line": 255, - "guard": null, - "pattern": "{:__aliases__, _, _} = alias, env", - "kind": "defp", - "end_line": 256, - "ast_sha": "14682cc624c36e71add79f5dda8643559feb44d59953f72e99bff25a6eb48f56", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "544e138d90d94520a4b56cf0d154fa795a6efa6dabf3ee662ebe659611dbc92c", - "start_line": 255, - "name": "expand_alias", - "arity": 2 - }, - "delete_csrf_token/0:1447": { - "line": 1447, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 1447, - "ast_sha": "bfbbbfbf40052e78fe56fefc9e05a6019921872ae52f896bbcc27bfd2a946bc0", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "2454c660cb1d4b78433c75774c1ada05f1ade465e655d95971b940bfa669ddbf", - "start_line": 1447, - "name": "delete_csrf_token", - "arity": 0 - }, - "persist_flash/2:1774": { - "line": 1774, - "guard": null, - "pattern": "conn, value", - "kind": "defp", - "end_line": 1775, - "ast_sha": "7d508fbc9dc8efa8afb0897ee1d483e0b1177ff74772a94a1e35dbd48a98c881", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "53729114a6d61675ff04507137e4c04eab729f8e7c7c1bd1a62bc782b707f00d", - "start_line": 1774, - "name": "persist_flash", - "arity": 2 - }, - "endpoint_module/1:340": { - "line": 340, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 340, - "ast_sha": "25c57886dff9672794edc565d9222218879b25187b189b0acbfca5af3357582d", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "3c406b281d92af193feb1bd84729d507b6cd28412a3edada86f50f87b5b07762", - "start_line": 340, - "name": "endpoint_module", - "arity": 1 - }, - "parse_exts/2:1603": { - "line": 1603, - "guard": null, - "pattern": "type, subtype", - "kind": "defp", - "end_line": 1603, - "ast_sha": "78329193b65df3c14b83ee3af9bee4c29aea7fa933f91d8f0eb87de6fd9eef88", - "source_file": "lib/phoenix/controller.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller.ex", - "source_sha": "6dc2f6ae9a4969f1da8405793bff02fb122f57ab697c9d553bb39d5cd89a645d", - "start_line": 1603, - "name": "parse_exts", - "arity": 2 - } - }, - "Phoenix.Param.Float": { - "__impl__/1:70": { - "line": 70, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 70, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "447a95046f2237b38d953cdb1dcf49b7b25be4043395a4c9446462456ae6865a", - "start_line": 70, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:71": { - "line": 71, - "guard": null, - "pattern": "float", - "kind": "def", - "end_line": 71, - "ast_sha": "16b840a66bcac7054a9817879985cc789dc9470f1ae80b81bf3863d0016a573e", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "ebd010a07494298469ba4811f4816b766234a1d277a17a2f912e6d1584b6b62c", - "start_line": 71, - "name": "to_param", - "arity": 1 - } - }, - "Phoenix.Endpoint.Watcher": { - "cd/1:59": { - "line": 59, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 59, - "ast_sha": "090c3e472461a3bc77b4b5a1559d9814eeadceff2decaa3d1a730a928adcf3c6", - "source_file": "lib/phoenix/endpoint/watcher.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", - "source_sha": "dcf7eb1f91c1b485c8302457ab12bb00a68de9c27a618f80b7474de148d28dda", - "start_line": 59, - "name": "cd", - "arity": 1 - }, - "start_link/1:13": { - "line": 13, - "guard": null, - "pattern": "{cmd, args}", - "kind": "def", - "end_line": 14, - "ast_sha": "3babca99d59ca9bdf47711f2ec57d4d66f02ae4cacd1352aa494ccc7983064e7", - "source_file": "lib/phoenix/endpoint/watcher.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", - "source_sha": "6334e5063f163ed7be119a5494ae079319b341b46e4d03d7e4be1d58e41dbe43", - "start_line": 13, - "name": "start_link", - "arity": 1 - }, - "watch/2:17": { - "line": 17, - "guard": null, - "pattern": "_cmd, {mod, fun, args}", - "kind": "def", - "end_line": 27, - "ast_sha": "8968d235362f977803df63b7633afb606046f9f929627392c7cf2572a4121386", - "source_file": "lib/phoenix/endpoint/watcher.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", - "source_sha": "4ecdff5ede7d6a7a6a8414c80d0716410c44e0293dacba819cf62e089d243322", - "start_line": 17, - "name": "watch", - "arity": 2 - }, - "watch/2:31": { - "line": 31, - "guard": "is_list(args)", - "pattern": "cmd, args", - "kind": "def", - "end_line": 55, - "ast_sha": "4b827ca8b5bbce1e6a3df74be2bd08e2629cd061aa57ad5b52ab7b39e8388f39", - "source_file": "lib/phoenix/endpoint/watcher.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/watcher.ex", - "source_sha": "513b0022e814a388872db99d84db5c77bb915c7df7c336ffa6cbe71092044d50", - "start_line": 31, - "name": "watch", - "arity": 2 - } - }, - "Mix.Tasks.Phx.Gen.Socket": { - "paths/0:113": { - "line": 113, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 113, - "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", - "start_line": 113, - "name": "paths", - "arity": 0 - }, - "raise_with_help/0:82": { - "line": 82, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 83, - "ast_sha": "db992a2f2b807e24c0021de430484b2f378852f947e538fa77e013ee80376ca2", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "afdfd3e5d30e0557dfdb9989299a9d0d52b3bc25de29f7c935ba5ea7d84db0d2", - "start_line": 82, - "name": "raise_with_help", - "arity": 0 - }, - "run/1:28": { - "line": 28, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 77, - "ast_sha": "3c4d1cea79a42054176b3500024898eee098f685fb5099db2d73a18126796480", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "dbd65b22ad80bcf21d57f466410c74ccbf158b068a178b9e3238938ced0edb43", - "start_line": 28, - "name": "run", - "arity": 1 - }, - "valid_name?/1:109": { - "line": 109, - "guard": null, - "pattern": "name", - "kind": "defp", - "end_line": 110, - "ast_sha": "116909eba9bf97ce2ec07a574ff6b32373f50a44f2af12b8e78e5a5bb51ebd17", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "6f11947844b4c7b3c737756284b91e5cf8fd88aa20d29257704fcd75a6a6e3ec", - "start_line": 109, - "name": "valid_name?", - "arity": 1 - }, - "validate_args!/1:107": { - "line": 107, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 107, - "ast_sha": "b7b4237b9a81f05dbe1f0cc5a0382bb38ebc3593f62bb4ba09dfe27512839627", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "eff2ea8fce27f866c70fab6574ddf30433b00959ba444b5538a0232d0df29bf7", - "start_line": 107, - "name": "validate_args!", - "arity": 1 - }, - "validate_args!/1:91": { - "line": 91, - "guard": null, - "pattern": "[name, \"--from-channel\", pre_existing_channel]", - "kind": "defp", - "end_line": 96, - "ast_sha": "1357d1ddd6b0c30ff071a0f141b2a64b638fcc1de9183936f4f82a0edd02bc85", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "a246f406bd97024f57f95ab90104c5eb33b9639a55fca1133e99260d2d835317", - "start_line": 91, - "name": "validate_args!", - "arity": 1 - }, - "validate_args!/1:99": { - "line": 99, - "guard": null, - "pattern": "[name]", - "kind": "defp", - "end_line": 104, - "ast_sha": "5d4951905121016be9e3c9e81d51cc1569e8ec94c522dc809ca3f21dacfc701b", - "source_file": "lib/mix/tasks/phx.gen.socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.socket.ex", - "source_sha": "28a6df1710e338c1831885628e675409340a7b3366a3258daae09c7485e50e7d", - "start_line": 99, - "name": "validate_args!", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": { - "build/1:13": { - "line": 13, - "guard": null, - "pattern": "\"bcrypt\"", - "kind": "def", - "end_line": 23, - "ast_sha": "3f32e30001742b4216918ee00a3de8a8fc485c177af2f43e8312e6031268b8e8", - "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_sha": "904da9edf6b27ebe0a3c73582971ba84d0f2b6ffebf42c5555915ab7508d1121", - "start_line": 13, - "name": "build", - "arity": 1 - }, - "build/1:26": { - "line": 26, - "guard": null, - "pattern": "\"pbkdf2\"", - "kind": "def", - "end_line": 36, - "ast_sha": "65f8dbec91247b6ebbe02e05e3b3dd591b1597ed6d6d6d163d1cc1db605aa013", - "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_sha": "e6478506b29e912d187aaddb1353d2277b83fd1aecd7278fabef606ac219bb9e", - "start_line": 26, - "name": "build", - "arity": 1 - }, - "build/1:39": { - "line": 39, - "guard": null, - "pattern": "\"argon2\"", - "kind": "def", - "end_line": 49, - "ast_sha": "2688a8e1b96e9adf5680651792e22f0c305bb8ae0a87ee07da6f57201491e13b", - "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_sha": "8c91b2da263b93e3cb727788efea447d093c56263d713eccdd5e0e3655c0141c", - "start_line": 39, - "name": "build", - "arity": 1 - }, - "build/1:52": { - "line": 52, - "guard": null, - "pattern": "other", - "kind": "def", - "end_line": 53, - "ast_sha": "fb79f1d77fc94e6a4a3bb14bd0ae9c39a00cc6ce0b08f8524acd64fd120669df", - "source_file": "lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/hashing_library.ex", - "source_sha": "ba4044406f0198445934f0b070ba02501124951bc8813367b1e4bba165a8f785", - "start_line": 52, - "name": "build", - "arity": 1 - } - }, - "Phoenix.Router.NoRouteError": { - "exception/1:8": { - "line": 8, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 16, - "ast_sha": "988fe8857827b216447b4e000a82ae02cac4ab8a3dbaf6fa20ac8a6bfd4b57ec", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "e1e48344b11cafaeaf332a567fe604cf96951a8d3262f4ae27f42dab97fa38b6", - "start_line": 8, - "name": "exception", - "arity": 1 - }, - "message/1:6": { - "line": 6, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 6, - "ast_sha": "51a2b9a745170c7e0700a65970170ef43382cc9b888edd9a4bdd2e656f5c3054", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "6ec747094a43bd6423990fa0574c42ea1ae3ba2ebd10a7a144091f89d14b017e", - "start_line": 6, - "name": "message", - "arity": 1 - } - }, - "Phoenix.Router.Helpers": { - "defhelper/2:250": { - "line": 250, - "guard": null, - "pattern": "%Phoenix.Router.Route{} = route, exprs", - "kind": "def", - "end_line": 265, - "ast_sha": "d753381d36d29c1d536669fecc44807d07dee199c3b0b14ce340f9fe6ad6cb7f", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "d2202fc501484c818c3fa7e7a2dfd868e71537b4665f8914a586b418d74dbd46", - "start_line": 250, - "name": "defhelper", - "arity": 2 - }, - "defhelper_catch_all/1:270": { - "line": 270, - "guard": null, - "pattern": "{helper, routes_and_exprs}", - "kind": "def", - "end_line": 298, - "ast_sha": "2b7c71907372d686e357da577ec7608fc99d1b54362337a16ff5c67db8b3a495", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "f92bd07e6175801ebd3c08e448e4f2d6950d4b1d98774f757d8a58abd077949c", - "start_line": 270, - "name": "defhelper_catch_all", - "arity": 1 - }, - "define/2:11": { - "line": 11, - "guard": null, - "pattern": "env, routes", - "kind": "def", - "end_line": 242, - "ast_sha": "2f5deb05fcfd989763cf633df052ac2de79df51795e63a708bb0c8dfca7483e5", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "8d7bb1b12f9487b463611cb493b41fbb70ce6e118e269e0b74c94ad8e8412f8d", - "start_line": 11, - "name": "define", - "arity": 2 - }, - "encode_param/1:350": { - "line": 350, - "guard": null, - "pattern": "str", - "kind": "def", - "end_line": 350, - "ast_sha": "781fcd9652340ae51f0c8d8bacd7062e62d00f5735bdd0e27a313e1f306d5786", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "15645be3d40fa3cdf66f88746d5e7a8682d3306ffb9dcb90a48a81ccc1ef9ca2", - "start_line": 350, - "name": "encode_param", - "arity": 1 - }, - "expand_segments/1:352": { - "line": 352, - "guard": null, - "pattern": "[]", - "kind": "defp", - "end_line": 352, - "ast_sha": "bdad58ab17a09c6000f23a8bcb6a806be3e7b5eab8c758543057b4257e2a4286", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "999de31b9fe8753d5a71a86ea88e200e02ecfea1d68b6bc8edb18bdeac3428cd", - "start_line": 352, - "name": "expand_segments", - "arity": 1 - }, - "expand_segments/1:354": { - "line": 354, - "guard": "is_list(segments)", - "pattern": "segments", - "kind": "defp", - "end_line": 355, - "ast_sha": "4afc402f946fd61855d509de1be2a317a0a48cdcb18f07755db6e376282949fa", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "57da7ff6218a06e0d2d4cb1beb7139cd2db4d9e764579bd3b589eb23911f0d67", - "start_line": 354, - "name": "expand_segments", - "arity": 1 - }, - "expand_segments/1:358": { - "line": 358, - "guard": null, - "pattern": "segments", - "kind": "defp", - "end_line": 359, - "ast_sha": "fb55ffad7f96c6af963eab1cac40f00a00b88a59f84ab3ef3bdbaad6e0e11333", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "7df1e56facb6b9c2ab7e17e93307557955211049a6f2cb0d744aeb9c4fe135c0", - "start_line": 358, - "name": "expand_segments", - "arity": 1 - }, - "expand_segments/2:362": { - "line": 362, - "guard": null, - "pattern": "[{:|, _, [h, t]}], acc", - "kind": "defp", - "end_line": 367, - "ast_sha": "fb31dd992c067a369e462318d2b8f4e239804f571b612fb03c5d8772b1b352d3", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "5de292998f8fa2222f00a2e4475dceab850dabb22cb59e7c72f780d650b8a1a4", - "start_line": 362, - "name": "expand_segments", - "arity": 2 - }, - "expand_segments/2:370": { - "line": 370, - "guard": "is_binary(h)", - "pattern": "[h | t], acc", - "kind": "defp", - "end_line": 371, - "ast_sha": "bd52db5cbc10743b8f8b7b988b7a93797972b9f5fdbe75a0d3b804aae2a016b3", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "d70c1e064a7d11307393bc2daaf60f97e20a330af30028442d973792458902ac", - "start_line": 370, - "name": "expand_segments", - "arity": 2 - }, - "expand_segments/2:373": { - "line": 373, - "guard": null, - "pattern": "[h | t], acc", - "kind": "defp", - "end_line": 377, - "ast_sha": "e61c0c7819bda27b1f649145f9d57fa6116bad97b9554a320b9b3e94b7be4b28", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "b51ad2d008c490cb89e2b0eb5355dff516c1739a8aa643d625571becc3ac9aa0", - "start_line": 373, - "name": "expand_segments", - "arity": 2 - }, - "expand_segments/2:380": { - "line": 380, - "guard": null, - "pattern": "[], acc", - "kind": "defp", - "end_line": 381, - "ast_sha": "138cce8fb555f568f9d4969efdae1f464677a889ec1e51dfcebf2b7f4c24884f", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "9fee30bf80f0648ad23bd26fc13d58c17022ce0734273e9ad87af5d019260dbd", - "start_line": 380, - "name": "expand_segments", - "arity": 2 - }, - "invalid_param_error/5:332": { - "line": 332, - "guard": null, - "pattern": "mod, fun, arity, action, routes", - "kind": "defp", - "end_line": 340, - "ast_sha": "089098dcba4f5d44e793907eb0b8dcdaba66c1661f9e80101229592cbc69b19a", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "05cca0a26ebd5ad623b3bcde94e733bf62509247365ce86518dac1086dc593e7", - "start_line": 332, - "name": "invalid_param_error", - "arity": 5 - }, - "invalid_route_error/3:321": { - "line": 321, - "guard": null, - "pattern": "prelude, fun, routes", - "kind": "defp", - "end_line": 329, - "ast_sha": "2c51aa70a7cb8857cccada14cb84ab133c273d56d51446022bd606a40c0c1bcb", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "db4c4d782b56a41b2bfca097b62647c3d4612a80ed735e75f0864cf82038425e", - "start_line": 321, - "name": "invalid_route_error", - "arity": 3 - }, - "raise_route_error/6:306": { - "line": 306, - "guard": null, - "pattern": "mod, fun, arity, action, routes, params", - "kind": "def", - "end_line": 317, - "ast_sha": "aadb04f816a752ed46cd8a7d6047734fd82f8b4d33fde709f4838fa006cca2de", - "source_file": "lib/phoenix/router/helpers.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/helpers.ex", - "source_sha": "b251107818d7306b619d0576f57b63d847cfe5181956c306ed60568ccbfb1f16", - "start_line": 306, - "name": "raise_route_error", - "arity": 6 - } - }, - "Phoenix.CodeReloader.Proxy": { - "child_spec/1:5": { - "line": 5, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 862, - "ast_sha": "d39d628946704cac279bb034b010ec426bb9a2f87c3667d921acf068e9346a7f", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "e4c2bc0f72c378111f17c3560f067711433dae27efbe607a74b147c584fb26ab", - "start_line": 5, - "name": "child_spec", - "arity": 1 - }, - "code_change/3:5": { - "line": 5, - "guard": null, - "pattern": "_old, state, _extra", - "kind": "def", - "end_line": 940, - "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "e4c2bc0f72c378111f17c3560f067711433dae27efbe607a74b147c584fb26ab", - "start_line": 5, - "name": "code_change", - "arity": 3 - }, - "diagnostic_to_chars/1:61": { - "line": 61, - "guard": null, - "pattern": "%{severity: :error, message: <<\"**\"::binary, _::binary>> = message}", - "kind": "defp", - "end_line": 62, - "ast_sha": "b649d98180fea9acc7bd1a877710222ef7854a0da73df235b010b94c321e1969", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "4d6751ca9faa4f287bce540c6c6c12ff73622fc87093bf23f3add4143fc938f8", - "start_line": 61, - "name": "diagnostic_to_chars", - "arity": 1 - }, - "diagnostic_to_chars/1:65": { - "line": 65, - "guard": "is_binary(file)", - "pattern": "%{severity: severity, message: message, file: file, position: position}", - "kind": "defp", - "end_line": 66, - "ast_sha": "f33d2324c07ff10008accd9952b47caeba5468cacbe727a099eda5709f60220c", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "f3e4017bc69d152c813b227e8e607bbfa82dbba0932a0009b8702e7069e6e80b", - "start_line": 65, - "name": "diagnostic_to_chars", - "arity": 1 - }, - "diagnostic_to_chars/1:69": { - "line": 69, - "guard": null, - "pattern": "%{severity: severity, message: message}", - "kind": "defp", - "end_line": 70, - "ast_sha": "bf102a678d9f3620494b736d2325cda9e3f125dd00b2be0f8b6e652294eb6595", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "fde584b706b8688f04d0a165c96df5014e50ae9e23d330319832d61801322436", - "start_line": 69, - "name": "diagnostic_to_chars", - "arity": 1 - }, - "diagnostics/2:11": { - "line": 11, - "guard": null, - "pattern": "proxy, diagnostics", - "kind": "def", - "end_line": 12, - "ast_sha": "9e78d2b9914d3d6945dc58726397cb81f23fa3d9be2542d961d51d31e260e848", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "4c670ede84a89965015389ccbdcceda1393ea26d0b0392a260e3f0d4ae63f363", - "start_line": 11, - "name": "diagnostics", - "arity": 2 - }, - "handle_call/3:29": { - "line": 29, - "guard": null, - "pattern": ":stop, _from, output", - "kind": "def", - "end_line": 30, - "ast_sha": "cfbe95b9150c1914519df4ef1a83139ec4b9416c528924b81a7df7212be0813a", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "5b7e841683db5546800e88f34fd2260801d1dba8a38d39dbba9a2c45c79a0a3d", - "start_line": 29, - "name": "handle_call", - "arity": 3 - }, - "handle_cast/2:25": { - "line": 25, - "guard": null, - "pattern": "{:diagnostics, diagnostics}, output", - "kind": "def", - "end_line": 26, - "ast_sha": "c79c133927c80dcf4d1ae47f9e105fdc92fb65c17508aaa638423b14e76d1377", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "f05971575c039fcfb7e32ebc186e3da6708a884c785c44328372c2b1c79691ca", - "start_line": 25, - "name": "handle_cast", - "arity": 2 - }, - "handle_info/2:33": { - "line": 33, - "guard": null, - "pattern": "msg, output", - "kind": "def", - "end_line": 52, - "ast_sha": "e9147d3c9c0341e572e9b534ab36f2688e26c65097ae25f35ee32fc9fb07b0b9", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "a0d5c28991aa1ea17eb6bf49bc1c0963a1c02b8f9e4e09a89202335121b930a8", - "start_line": 33, - "name": "handle_info", - "arity": 2 - }, - "init/1:21": { - "line": 21, - "guard": null, - "pattern": ":ok", - "kind": "def", - "end_line": 21, - "ast_sha": "1333ab1920c76e3b15e016d4aaf48b7d42e235e282199ec0d070d9efda509748", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "66bd5ffb86957db83e516b90a67f1c99358bce4382ac5ce2d9128aa45d92fd89", - "start_line": 21, - "name": "init", - "arity": 1 - }, - "position/1:73": { - "line": 73, - "guard": null, - "pattern": "{line, col}", - "kind": "defp", - "end_line": 73, - "ast_sha": "177fb2267f686456337c3ab08ba8f98f8c47ed815c463cf0b0960fac50e710b5", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "57fa0844cbf4e09e840a80e21c3527107a78aa4b94efef19779995a366e29a0a", - "start_line": 73, - "name": "position", - "arity": 1 - }, - "position/1:74": { - "line": 74, - "guard": "is_integer(line) and line > 0", - "pattern": "line", - "kind": "defp", - "end_line": 74, - "ast_sha": "685d54a23dbaabf240d35388fa37a53de0bc25e3239f5ac1052bebb8610f09f7", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "00f00123830d91520a83ffd556ffed679be46d30c853c35e6cd4ef743cf17a61", - "start_line": 74, - "name": "position", - "arity": 1 - }, - "position/1:75": { - "line": 75, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 75, - "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "d6f7b129b37e6565fc95d462cf6b01756fcfbadd22f0fc13efd929dfff26fe98", - "start_line": 75, - "name": "position", - "arity": 1 - }, - "put_chars/4:56": { - "line": 56, - "guard": null, - "pattern": "from, reply, chars, output", - "kind": "defp", - "end_line": 58, - "ast_sha": "a422d404cb3134418ec99761807c93908a3042dab446ef38c7aae93564ed96d7", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "115c0e82b24b88bffe526730b87193551ff82d7ead9fcbbba846ef83bc0c24b7", - "start_line": 56, - "name": "put_chars", - "arity": 4 - }, - "start/0:7": { - "line": 7, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 8, - "ast_sha": "1068fcdd9c8dccdbbac222ed0f19dffece400050c21288c471b7df4b46627c68", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "9943ad29f30d2483fc104784fc409c861a69891be038bdbd981e41e52e7e27bb", - "start_line": 7, - "name": "start", - "arity": 0 - }, - "stop/1:15": { - "line": 15, - "guard": null, - "pattern": "proxy", - "kind": "def", - "end_line": 16, - "ast_sha": "0668bfa31d09f13697951d49b0206405b49360d8a6e4f6000bc05bec351802ea", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "2e35e474ee5c3e3465c583585a9ce58302fac0acb4fdd727a3d4401ffde5f366", - "start_line": 15, - "name": "stop", - "arity": 1 - }, - "terminate/2:5": { - "line": 5, - "guard": null, - "pattern": "_reason, _state", - "kind": "def", - "end_line": 5, - "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", - "source_file": "lib/phoenix/code_reloader/proxy.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/proxy.ex", - "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", - "start_line": 5, - "name": "terminate", - "arity": 2 - } - }, - "Phoenix.ActionClauseError": { - "__struct__/0:47": { - "line": 47, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 47, - "ast_sha": "0fc0146830ec1659e91eaade37d7a373aeddb8ede37faa33e1ba540633ea32fd", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", - "start_line": 47, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:47": { - "line": 47, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 47, - "ast_sha": "df77ef2167ef692ea2294b1e2d1e2c5daad0841d6d52269566a7c50aa3a06506", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", - "start_line": 47, - "name": "__struct__", - "arity": 1 - }, - "blame/2:57": { - "line": 57, - "guard": null, - "pattern": "exception, stacktrace", - "kind": "def", - "end_line": 65, - "ast_sha": "e6b5582e09c4675d7a4ef92da1d882a761c6b6c35c994374ad42a45a604f221e", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "6df6865bf2b6db488bb027ba10726ccde97f58747cf8fe5b79fc2e3fc8383b99", - "start_line": 57, - "name": "blame", - "arity": 2 - }, - "exception/1:47": { - "line": 47, - "guard": "is_list(args)", - "pattern": "args", - "kind": "def", - "end_line": 47, - "ast_sha": "b604e12ac1ef01393bc4b1f1415c7c50743e32117df6cf4843d7ffa0a2346cf3", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "4af1ce3d78b54bc367a288a8443918b9ab74450b7589bc316e340a8cf84c120d", - "start_line": 47, - "name": "exception", - "arity": 1 - }, - "message/1:50": { - "line": 50, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 53, - "ast_sha": "82050b73f3c8907643c3b17591a4c900e4a695b9fb4519e6a9bff003cf3f400c", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "59f06ee6f7b308a0f6b254398319c4b5b89f72a10ebfb05902e07269c88c2b96", - "start_line": 50, - "name": "message", - "arity": 1 - } - }, - "Phoenix.Socket": { - "user_connect/6:622": { - "line": 622, - "guard": null, - "pattern": "handler, endpoint, transport, serializer, params, connect_info", - "kind": "defp", - "end_line": 676, - "ast_sha": "50bf50998ff9ae42839655c3dee465ed3d14067ebeceea2feeef3d0cf7420d12", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "510d9958cc34e505e97735deb2b80ac3b0d913a3ae718bdbf245a9db320452df", - "start_line": 622, - "name": "user_connect", - "arity": 6 - }, - "encode_reply/2:838": { - "line": 838, - "guard": null, - "pattern": "%{serializer: serializer}, message", - "kind": "defp", - "end_line": 840, - "ast_sha": "657e86aae8e96a9f28e2ddc5b4aeaa09eb085d1ae20b8fce7977ea7c86cabe1c", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "f198d05d038f4e5356e533592dd2cf948c3743522d3e71b178692e208b3c7f4f", - "start_line": 838, - "name": "encode_reply", - "arity": 2 - }, - "handle_in/4:695": { - "line": 695, - "guard": null, - "pattern": "nil, %{event: \"phx_join\", topic: topic, ref: ref, join_ref: join_ref} = message, state, socket", - "kind": "defp", - "end_line": 730, - "ast_sha": "5107e6a577043defff9147e1801625be2e956f7a9c4e3581e943a5c551259062", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "cf3802585731950bce0e654c720161118369135a8b113f5a6b463df5e2a9bfcb", - "start_line": 695, - "name": "handle_in", - "arity": 4 - }, - "channel/3:397": { - "line": 397, - "guard": null, - "pattern": "topic_pattern, module, opts", - "kind": "defmacro", - "end_line": 408, - "ast_sha": "d315cc956e55202f2cbdd04b256f7a9f1798dae897c61abd25c6ab68b4ece91e", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "b75f2e2dea3c41e0826c70f20acb6733bf8ed2edfa44f7ca344847787b8d93e8", - "start_line": 397, - "name": "channel", - "arity": 3 - }, - "__info__/2:562": { - "line": 562, - "guard": null, - "pattern": ":socket_drain, state", - "kind": "def", - "end_line": 564, - "ast_sha": "ea289c3336b85517c7d20ea3acd8756f02af9e88ea04c385e44e60ac764f37c0", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "13d602a078b9f62f1dcd02116a50ad3c1ab1ba61ea759eb785ec0c97ec0ca1d8", - "start_line": 562, - "name": "__info__", - "arity": 2 - }, - "socket_close/2:868": { - "line": 868, - "guard": null, - "pattern": "pid, {state, socket}", - "kind": "defp", - "end_line": 876, - "ast_sha": "1390ce5511d100e606785c99c4b3aafa275244d012013645488abf21973eff24", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "eb4404f7aa7c3158271fe8bdc04d73fdd1eb7defb56eabc8f621c283bfb74978", - "start_line": 868, - "name": "socket_close", - "arity": 2 - }, - "set_label/1:531": { - "line": 531, - "guard": null, - "pattern": "socket", - "kind": "defp", - "end_line": 533, - "ast_sha": "3fe08f2dbb543fc29c11062214d9ef857f8e165a7e1911f8f84069d8d3776b3c", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "b942772b216b1e9b121fa2c8b6c6ab01413363f24d8cc84bb74cb4f698f41fd1", - "start_line": 531, - "name": "set_label", - "arity": 1 - }, - "to_topic_match/1:442": { - "line": 442, - "guard": null, - "pattern": "topic_pattern", - "kind": "defp", - "end_line": 446, - "ast_sha": "8bba8c0a877983cd0f445e15dd8417271cc13798e53636bc2952c58d2851fd82", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "44aa97be50773fa62b86c557cd32625c069b2e9699aa4e9ffad7d6738ddc8e70", - "start_line": 442, - "name": "to_topic_match", - "arity": 1 - }, - "expand_alias/2:412": { - "line": 412, - "guard": null, - "pattern": "{:__aliases__, _, _} = alias, env", - "kind": "defp", - "end_line": 413, - "ast_sha": "82c00e1b2e922270a189153b46db4973d0df716717df67cb9f27491a8088c9ff", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d910d5007abe499f9a53fe4beff3dfeeb71a706d9443fe2e87124362603281d7", - "start_line": 412, - "name": "expand_alias", - "arity": 2 - }, - "negotiate_serializer/2:598": { - "line": 598, - "guard": "is_list(serializers)", - "pattern": "serializers, vsn", - "kind": "defp", - "end_line": 617, - "ast_sha": "b76f3d227f323c9a42b5105d834c22bd2880069c092fe713a537415478b82666", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "0f2faeefd4a365153a1c86524a5da07b965c1b0553b64ab7ff785da411694fa4", - "start_line": 598, - "name": "negotiate_serializer", - "arity": 2 - }, - "__terminate__/2:594": { - "line": 594, - "guard": null, - "pattern": "_reason, _state_socket", - "kind": "def", - "end_line": 594, - "ast_sha": "206cec333f0a4f8ef4aac9354c8055e02ff9ebd0979518b17c29ad2c6c0ecf90", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "8f78f7cab4b48f26b9375469a3ec187c5ed225040e9d204d165f84e760c360cc", - "start_line": 594, - "name": "__terminate__", - "arity": 2 - }, - "put_channel/4:806": { - "line": 806, - "guard": null, - "pattern": "state, pid, topic, join_ref", - "kind": "defp", - "end_line": 813, - "ast_sha": "97e39f2fe08ec1d9fa87be6e81446596da94004f195e09871a159e790c7c3668", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "9718754f5e1f6748a947f2643291f54989c9ef8d4be78ea6f68ca7e4213a48e9", - "start_line": 806, - "name": "put_channel", - "arity": 4 - }, - "handle_in/4:734": { - "line": 734, - "guard": null, - "pattern": "{pid, _ref, status}, %{event: \"phx_join\", topic: topic} = message, state, socket", - "kind": "defp", - "end_line": 750, - "ast_sha": "d98cf16daa9f3f915303e996564fd7c4b9b107aa09121175e0ee65b722cecf93", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "522fe7ab449f5fb47ab0033ed95408bc2440bf6099c55999c49fe78dc121e5d7", - "start_line": 734, - "name": "handle_in", - "arity": 4 - }, - "__info__/2:571": { - "line": 571, - "guard": null, - "pattern": "{:socket_close, pid, _reason}, state", - "kind": "def", - "end_line": 572, - "ast_sha": "ec15a691354149d56bc87224f07f5e118e04c86ce4bfddd312eee2245083cdb0", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "108a402f0277c3be3967b2a6f75a5ab43a88c6b1fc716dfa2a6ee8fed85a336a", - "start_line": 571, - "name": "__info__", - "arity": 2 - }, - "expand_alias/2:415": { - "line": 415, - "guard": null, - "pattern": "other, _env", - "kind": "defp", - "end_line": 415, - "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", - "start_line": 415, - "name": "expand_alias", - "arity": 2 - }, - "__before_compile__/1:423": { - "line": 423, - "guard": null, - "pattern": "env", - "kind": "defmacro", - "end_line": 437, - "ast_sha": "3dd7ff8e077ee898a9f89f31f87ebb382ba4f99b9085147efb6a7e19bb289a13", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "6420a94f90c92c39abb7e23c71eaa35b10c3be3c14b518d7f647cf7115c37292", - "start_line": 423, - "name": "__before_compile__", - "arity": 1 - }, - "assign/2:362": { - "line": 362, - "guard": "is_map(keyword_or_map) or is_list(keyword_or_map)", - "pattern": "%Phoenix.Socket{} = socket, keyword_or_map", - "kind": "def", - "end_line": 364, - "ast_sha": "ad90868d8912a9daad38e22b8ebeb1da3824f61ca0ac4d28aa610e0e388c16a0", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "4152cffd3df519d7742886ac03e37c02bf53a9ff390517f12395594a40795604", - "start_line": 362, - "name": "assign", - "arity": 2 - }, - "__struct__/1:257": { - "line": 257, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 257, - "ast_sha": "f649eca2bee634cfd528e4b8354fb08d5a046888513f8785f441ee973f4eda7e", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "e60eea24791c55c319855ad886eae033c9597db77c90f6397c58c34d4fb01c25", - "start_line": 257, - "name": "__struct__", - "arity": 1 - }, - "__info__/2:558": { - "line": 558, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{event: \"disconnect\"}, state", - "kind": "def", - "end_line": 559, - "ast_sha": "0818be9e3e9bdd8460ccd4319ac15295538a503f931b7c44330c555eabf10bf3", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d1a2b3dba28c0979bd566b77b0dbcf350429024031f9ba3006b261049d39b08b", - "start_line": 558, - "name": "__info__", - "arity": 2 - }, - "update_channel_status/4:880": { - "line": 880, - "guard": null, - "pattern": "state, pid, topic, status", - "kind": "defp", - "end_line": 882, - "ast_sha": "0e0ac0e98831f9356936a84e39f04ad4dbc2e1feb4a460089fffbbca6134e1dc", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "5919524c48a921e9c26d41d3c29553b0f21cac46ea63b64854efac4bacf046f6", - "start_line": 880, - "name": "update_channel_status", - "arity": 4 - }, - "__info__/2:580": { - "line": 580, - "guard": null, - "pattern": "{:debug_channels, ref, reply_to}, {state, socket}", - "kind": "def", - "end_line": 587, - "ast_sha": "bf5b38bf379b232824ed04931402bd47471ea2c11e02a40e48d432c5a964d82d", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "cf5373bd5814202e09f4e9eb70686859cc05378876b47ae66c3f94f2fda72b0a", - "start_line": 580, - "name": "__info__", - "arity": 2 - }, - "__struct__/0:257": { - "line": 257, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 257, - "ast_sha": "4fe472087621da2629bb451dd5ad5182c4bf4ba96fea314f9b6870b059675f17", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "e60eea24791c55c319855ad886eae033c9597db77c90f6397c58c34d4fb01c25", - "start_line": 257, - "name": "__struct__", - "arity": 0 - }, - "__info__/2:567": { - "line": 567, - "guard": null, - "pattern": "{:socket_push, opcode, payload}, state", - "kind": "def", - "end_line": 568, - "ast_sha": "c083e72058b94eabb77cf05dbd6aecaed8d342cae67426fee886e828760047e4", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "00881cd0ba44c6a7a5eaba161c6b927a805cb6be527bfff0534e02de8b18fa9f", - "start_line": 567, - "name": "__info__", - "arity": 2 - }, - "handle_in/4:768": { - "line": 768, - "guard": null, - "pattern": "{pid, _ref, _status}, msg, state, socket", - "kind": "defp", - "end_line": 779, - "ast_sha": "f2f07fb5eab23450b41094c9e1f400023060b04f8b469bb375aae1c1cb7a477d", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "a3099a22c3e309a51508599a7ad200b4345cbfb13b2c79b5532e88290755fc2e", - "start_line": 768, - "name": "handle_in", - "arity": 4 - }, - "assign/2:367": { - "line": 367, - "guard": "is_function(fun, 1)", - "pattern": "%Phoenix.Socket{} = socket, fun", - "kind": "def", - "end_line": 368, - "ast_sha": "5dec69379ffb3d3521abff6e1fcfa139dc7c1b484377408f29e50b741311bec0", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "282a050974e43c838edda53911a02755e2fe45baa895452212c4de33f8109055", - "start_line": 367, - "name": "assign", - "arity": 2 - }, - "__child_spec__/3:458": { - "line": 458, - "guard": null, - "pattern": "handler, opts, socket_options", - "kind": "def", - "end_line": 463, - "ast_sha": "02f8b72d2f79274f92e83607d9b4e183ee3496fbcd8f6b3de54b0c6b3b049edb", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "22aa442453db5f0f431ff87762eeca07323e6eda7c4613779fd67dc5c183648f", - "start_line": 458, - "name": "__child_spec__", - "arity": 3 - }, - "defchannel/3:450": { - "line": 450, - "guard": null, - "pattern": "topic_match, channel_module, opts", - "kind": "defp", - "end_line": 452, - "ast_sha": "c057e1815f2cef51edf85f71dd91b787b191d658865a6f539aa9fb29c29fcdf4", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "e46a9998bf631d13493869de673066baedecc4fc0449bb49ea059d3b70d15225", - "start_line": 450, - "name": "defchannel", - "arity": 3 - }, - "encode_ignore/2:833": { - "line": 833, - "guard": null, - "pattern": "socket, %{ref: ref, topic: topic}", - "kind": "defp", - "end_line": 835, - "ast_sha": "a5098c3df66d0a4282be16a02ead510601e55e025aee7135c6510940b990050f", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "59629af6ad47a6ca4ccc8feaec7b7f4185858413be5084b5b6c83d68a511984d", - "start_line": 833, - "name": "encode_ignore", - "arity": 2 - }, - "handle_in/4:753": { - "line": 753, - "guard": null, - "pattern": "{pid, _ref, _status}, %{event: \"phx_leave\"} = msg, state, socket", - "kind": "defp", - "end_line": 764, - "ast_sha": "7656f1f50c958a786ec00b4be92ee19122ea1de94072f2b39a74a6eb45f6b763", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "232440c0bd5394ac44897e36366cec5a73fc129ecb140116188505a996b806dc", - "start_line": 753, - "name": "handle_in", - "arity": 4 - }, - "__using__/1:290": { - "line": 290, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 298, - "ast_sha": "1a0d647674d3ec79622a36b9e149f52eb529357a41f8948eaec98a2b65dc2370", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "0a8ac0c1e3d9d335c2a7477a5f8753362a62bdb73d2a62f134dccfc003253b37", - "start_line": 290, - "name": "__using__", - "arity": 1 - }, - "assign/3:342": { - "line": 342, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket, key, value", - "kind": "def", - "end_line": 343, - "ast_sha": "b6f4572dbf953a6bc43033beb7afd70982114e8ec4fc11b89e0a9a85e84c3af1", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d701c1fc97f889703e7452edfc64510fa6d1268491d46ebff488ff7cc9286d13", - "start_line": 342, - "name": "assign", - "arity": 3 - }, - "transport/3:419": { - "line": 419, - "guard": null, - "pattern": "_name, _module, _config", - "kind": "defmacro", - "end_line": 419, - "ast_sha": "4c8b6da0dc80be17d3eb95dacaf4bceaed3c7844bce2fee7aff2b076a8c95422", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "0632dfdb3a0fe67fa0e8bbcded930e2c3078d954cbc1adac2969914040b0a41f", - "start_line": 419, - "name": "transport", - "arity": 3 - }, - "result/1:529": { - "line": 529, - "guard": null, - "pattern": "{:error, _}", - "kind": "defp", - "end_line": 529, - "ast_sha": "f20d11584b9475f1553b95ee4e5feafcc87ca44d116dd4bf743a0943d983b40c", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "2509ab75c4d1bff2980dc29a7a069f707fbe5910ef30a4daa6f023c35099c2c5", - "start_line": 529, - "name": "result", - "arity": 1 - }, - "__info__/2:575": { - "line": 575, - "guard": null, - "pattern": ":garbage_collect, state", - "kind": "def", - "end_line": 577, - "ast_sha": "a4ee1aab516d6e8b107adb305182cf208978385eb6a7bc5b94508b7fa522ad9b", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "0c02a499c046d24da69f179b4b5007c19c5fbbf2a73285e42872a311d7b03398", - "start_line": 575, - "name": "__info__", - "arity": 2 - }, - "handle_in/4:684": { - "line": 684, - "guard": null, - "pattern": "_, %{ref: ref, topic: \"phoenix\", event: \"heartbeat\"}, state, socket", - "kind": "defp", - "end_line": 692, - "ast_sha": "4077788f1c2a5e0da0a44e4a08c563c92186d49a4a668fea4cf9c7f659d917c6", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "8651f7dd6e14514253594797cb31507afb8dbea47e6d6afb091c57b131649db4", - "start_line": 684, - "name": "handle_in", - "arity": 4 - }, - "delete_channel/4:817": { - "line": 817, - "guard": null, - "pattern": "state, pid, topic, monitor_ref", - "kind": "defp", - "end_line": 824, - "ast_sha": "2fa094bb970b313d518dd3f9c0c9b69bc7d66200bcc68b017bea776d0dc27ca6", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "f29c15cf11bf5732605afc3ae3a8f1ab1623e94b273a55ac86fb20995c4045ba", - "start_line": 817, - "name": "delete_channel", - "arity": 4 - }, - "handle_in/4:783": { - "line": 783, - "guard": null, - "pattern": "nil, %{event: \"phx_leave\", ref: ref, topic: topic, join_ref: join_ref}, state, socket", - "kind": "defp", - "end_line": 797, - "ast_sha": "74f5476b928d44b9632451094c795e3f485e53b37770e8c58890d3b24f988ff1", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "e732262dca1443293c126a9f547a964eebf957fdb6282cef6d9023253a4e3197", - "start_line": 783, - "name": "handle_in", - "arity": 4 - }, - "__drainer_spec__/3:466": { - "line": 466, - "guard": null, - "pattern": "handler, opts, socket_options", - "kind": "def", - "end_line": 482, - "ast_sha": "c70791190634f22c84517b45ac62a5a6ea0683e7ca39084325d886c38e91318d", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "290ff6ca9fda2ad2d1933c608876c449b182941fdcb5597902bffaca1cb5d4f7", - "start_line": 466, - "name": "__drainer_spec__", - "arity": 3 - }, - "result/1:528": { - "line": 528, - "guard": null, - "pattern": ":error", - "kind": "defp", - "end_line": 528, - "ast_sha": "275536599397a6bb53631c3a0c687e558e4f47b7dd28414e9b2e105b25a48be7", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "a9852de8b6fd992023a1c8966eea4c7c325889560787bc779c77fe56f83354a0", - "start_line": 528, - "name": "result", - "arity": 1 - }, - "result/1:527": { - "line": 527, - "guard": null, - "pattern": "{:ok, _}", - "kind": "defp", - "end_line": 527, - "ast_sha": "a93b9923b29170761a8ba926d2f71cb06c7887e177d34d07844065f8935fec43", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "9199e1dccb9bd475f5b5c6f0a1b124359cd27a52e34458f44b525b869a4b9084", - "start_line": 527, - "name": "result", - "arity": 1 - }, - "channel/2:397": { - "line": 397, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 397, - "ast_sha": "0a71ff97caac2170228be47baca7ce80ac9fd2b40ff8c1a225882e4871de9203", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "dc111ee6521b2960bb1853b34ef4a4f128b32b6404f212a948e2c3f737783047", - "start_line": 397, - "name": "channel", - "arity": 2 - }, - "__connect__/3:488": { - "line": 488, - "guard": null, - "pattern": "user_socket, map, socket_options", - "kind": "def", - "end_line": 522, - "ast_sha": "c59513d5a3369ff336baa7814951f0e298b0c7aac459f6081774c082715a2046", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d894e0e07a1a20a10f024898ebf9681fba9af5521f8af479dd778ebe1e954323", - "start_line": 488, - "name": "__connect__", - "arity": 3 - }, - "__info__/2:590": { - "line": 590, - "guard": null, - "pattern": "_, state", - "kind": "def", - "end_line": 591, - "ast_sha": "befa2369a21a2819de00ca6c3deb97e278f59f96ebe731b8a9c9222d561cd121", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "411f7ec81367cb9c4a87c63fe8ec1d1b16880df779743f4041bb471d3ea5f6d0", - "start_line": 590, - "name": "__info__", - "arity": 2 - }, - "shutdown_duplicate_channel/1:855": { - "line": 855, - "guard": null, - "pattern": "pid", - "kind": "defp", - "end_line": 864, - "ast_sha": "db0d7d9463147e6ba02907a9d713b5113e37c18bd296e272c34e1a2f43abec4f", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "ba661781b66129201b1f2dac396c39115c78e2aa8ba4aabd2a1fa2a4f6bda4f8", - "start_line": 855, - "name": "shutdown_duplicate_channel", - "arity": 1 - }, - "handle_in/4:800": { - "line": 800, - "guard": null, - "pattern": "nil, message, state, socket", - "kind": "defp", - "end_line": 803, - "ast_sha": "001427cb73fdada3df639826e8277143ffde6da0ac8a3cf4ce48278bc65b1afd", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "159b08315805c2e706dae7e542ec04c830ab558f87a66e0d6e0587b375cc2167", - "start_line": 800, - "name": "handle_in", - "arity": 4 - }, - "__in__/2:542": { - "line": 542, - "guard": null, - "pattern": "{payload, opts}, {state, socket}", - "kind": "def", - "end_line": 544, - "ast_sha": "ee37802fc88f4089dd3a04e7b8c5f41611e4d55f5597d771fb946f51825884b1", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "056d6bb54537e8b32afe375d1a4895fd40340a1d264364a472e8333da7390ee9", - "start_line": 542, - "name": "__in__", - "arity": 2 - }, - "__info__/2:547": { - "line": 547, - "guard": null, - "pattern": "{:DOWN, ref, _, pid, reason}, {state, socket}", - "kind": "def", - "end_line": 554, - "ast_sha": "2432914dcdee220291c63e8c14b045a323a5f5d082e708b23c61f3bd3c40ce93", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "b5c25f4c52db6112acc31c31ee1187b0ef318d4323613a76e2152a840255f5e4", - "start_line": 547, - "name": "__info__", - "arity": 2 - }, - "transport/2:419": { - "line": 419, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 419, - "ast_sha": "c9aea0b46e577fe17d27eb82eaffe854bf18c4bd75128cab38eb6a48272a204a", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "0632dfdb3a0fe67fa0e8bbcded930e2c3078d954cbc1adac2969914040b0a41f", - "start_line": 419, - "name": "transport", - "arity": 2 - }, - "__init__/1:536": { - "line": 536, - "guard": null, - "pattern": "{state, %{id: id, endpoint: endpoint} = socket}", - "kind": "def", - "end_line": 539, - "ast_sha": "6dfa463d9d6d4712956cb96c36f129e480fe0e167f48bbd08800ea13a3660f0c", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "410eff737ce1dd10b5b319c6d72f3aed49739a748a0749cccbc1492f5aabddaa", - "start_line": 536, - "name": "__init__", - "arity": 1 - }, - "encode_close/3:843": { - "line": 843, - "guard": null, - "pattern": "socket, topic, join_ref", - "kind": "defp", - "end_line": 852, - "ast_sha": "77fe0170b8b0ab05ca3d6b05418f7b95a8e5c26bf63cf4bb42fb0a7eea6f09d1", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "554231a5b6efbebfac50812d35d6598cc60021afe86f204a8a0f0cd5172bd618", - "start_line": 843, - "name": "encode_close", - "arity": 3 - }, - "encode_on_exit/4:828": { - "line": 828, - "guard": null, - "pattern": "socket, topic, ref, _reason", - "kind": "defp", - "end_line": 830, - "ast_sha": "fd0be6b6cad4fc4f9685848f13ae6f51f9793a1c2914ae5dc98b65f18d890582", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "e4fd12d4930de9f4b83803c5702195dfeb3559a06e23dabccb251d17fc63d393", - "start_line": 828, - "name": "encode_on_exit", - "arity": 4 - } - }, - "Phoenix.Digester.Gzip": { - "compress_file/2:7": { - "line": 7, - "guard": null, - "pattern": "file_path, content", - "kind": "def", - "end_line": 9, - "ast_sha": "43ac78ad17d605c1c2769068259c34cadf65916da828778cb9f06776135ef6d1", - "source_file": "lib/phoenix/digester/gzip.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester/gzip.ex", - "source_sha": "466360c4ea839c2c1d311544a1cf90a3c2cbefd0b9cfeba8f340436a17d4af18", - "start_line": 7, - "name": "compress_file", - "arity": 2 - }, - "file_extensions/0:15": { - "line": 15, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 15, - "ast_sha": "8873827b20bb040f20e74a7cc92a53569d1bcb1d333dff4f4345828fe8a34513", - "source_file": "lib/phoenix/digester/gzip.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester/gzip.ex", - "source_sha": "503bb1ca84a6fa92fa037631264b10495ec14f75b7341c9e30a5899024ca86b5", - "start_line": 15, - "name": "file_extensions", - "arity": 0 - } - }, - "Phoenix": { - "json_library/0:47": { - "line": 47, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 48, - "ast_sha": "f53a34ba4f6e517bd7588e8165d18b510f2e450729a8e6e7d648725c7345ec75", - "source_file": "lib/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "source_sha": "12f9fb90bce89a9cae2ceecc4c1e25e301540bb38a156db6c434f35833a231e7", - "start_line": 47, - "name": "json_library", - "arity": 0 - }, - "plug_init_mode/0:61": { - "line": 61, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 62, - "ast_sha": "6ab4cd9e2da1ae6e801e577595f0088788f7f2ed23a7691ca554a6a49fffdc8a", - "source_file": "lib/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "source_sha": "9b0f1c25bae1be6f2ca36a6306c3e93945dd8d1b76da93117a4b10d09cbba898", - "start_line": 61, - "name": "plug_init_mode", - "arity": 0 - }, - "start/2:10": { - "line": 10, - "guard": null, - "pattern": "_type, _args", - "kind": "def", - "end_line": 35, - "ast_sha": "84fea3994d539fdb36cebdb7dd1a59ddb0caaa5b574566d4756fafae84ad51a4", - "source_file": "lib/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "source_sha": "6295dd6b82e9bc652ad5d33645c491480a6556d12fa0f752cd2bb6aeaacdb876", - "start_line": 10, - "name": "start", - "arity": 2 - }, - "stop/1:7": { - "line": 7, - "guard": null, - "pattern": "_state", - "kind": "def", - "end_line": 7, - "ast_sha": "09fe6e37b419a2fab24e390e3208139125f69da76332b3936618bbe4aba75bdb", - "source_file": "lib/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "source_sha": "644a30f07bb3dda540830b2cdb68554d53633551dd3787e8ee28b211c6b8c7b7", - "start_line": 7, - "name": "stop", - "arity": 1 - }, - "warn_on_missing_json_library/0:65": { - "line": 65, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 72, - "ast_sha": "4d343c6745b1e86f35b3ff7b6aa2dc217f4daa1a1d809fb487565b443b11826f", - "source_file": "lib/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix.ex", - "source_sha": "6642c17afba5de65d0dbc3bbc8fc3e13a5c35d58f1dd0923a1aa53151edf0de6", - "start_line": 65, - "name": "warn_on_missing_json_library", - "arity": 0 - } - }, - "Mix.Tasks.Phx.Gen.Channel": { - "paths/0:118": { - "line": 118, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 118, - "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", - "source_file": "lib/mix/tasks/phx.gen.channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", - "start_line": 118, - "name": "paths", - "arity": 0 - }, - "raise_with_help/0:97": { - "line": 97, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 98, - "ast_sha": "f540f7db0ebd112912d17a857338bbf2f0b02a000d4736fedd043c28c79268e9", - "source_file": "lib/mix/tasks/phx.gen.channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "source_sha": "afdfd3e5d30e0557dfdb9989299a9d0d52b3bc25de29f7c935ba5ea7d84db0d2", - "start_line": 97, - "name": "raise_with_help", - "arity": 0 - }, - "valid_name?/1:114": { - "line": 114, - "guard": null, - "pattern": "name", - "kind": "defp", - "end_line": 115, - "ast_sha": "c83c3a804cce744198355059e76845ea33d69386df3ddf0fcdbdc5dbb27fec90", - "source_file": "lib/mix/tasks/phx.gen.channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "source_sha": "6f11947844b4c7b3c737756284b91e5cf8fd88aa20d29257704fcd75a6a6e3ec", - "start_line": 114, - "name": "valid_name?", - "arity": 1 - }, - "validate_args!/1:106": { - "line": 106, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 111, - "ast_sha": "08e664382ac7c13ced6a99544f6de7384061733b4b6f29ff9c7a95eed4d18c0e", - "source_file": "lib/mix/tasks/phx.gen.channel.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.channel.ex", - "source_sha": "c363e9384baff9d465dd2bd0415896e94eeea5c509c56742db6633ef81b95410", - "start_line": 106, - "name": "validate_args!", - "arity": 1 - } - }, - "Phoenix.Socket.Transport": { - "host_to_binary/1:652": { - "line": 652, - "guard": null, - "pattern": "{:system, env_var}", - "kind": "defp", - "end_line": 652, - "ast_sha": "fd2778b21966cabc3331dfc919aeee3c5998662ee9d271610e2296c995c48e55", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "06135c36fd39f1fdbe33ca15c51ff20ed357624a256b594b48cdc7b7ab67f9ee", - "start_line": 652, - "name": "host_to_binary", - "arity": 1 - }, - "check_subprotocols/2:399": { - "line": 399, - "guard": null, - "pattern": "%Plug.Conn{halted: true} = conn, _subprotocols", - "kind": "def", - "end_line": 399, - "ast_sha": "7b8670013439598b1f8e50fbd23e0f7703268e470f40d7087e5056993888b3a3", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "858214eba5e1053a0d2fc70cb26738c3febbfb3eecbe5b4478bd72a3dee81872", - "start_line": 399, - "name": "check_subprotocols", - "arity": 2 - }, - "fetch_headers/2:535": { - "line": 535, - "guard": null, - "pattern": "conn, prefix", - "kind": "defp", - "end_line": 538, - "ast_sha": "6b097d89a32f58bfa27026a8c8fc97cfac0121e247aedd3ee4e591b884f9ee3c", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "d0230fdbf4776038363b790e7b1ea0107b29513279c2d23aab9392811b9e5ef6", - "start_line": 535, - "name": "fetch_headers", - "arity": 2 - }, - "compare_host?/2:648": { - "line": 648, - "guard": null, - "pattern": "request_host, allowed_host", - "kind": "defp", - "end_line": 649, - "ast_sha": "633f05474b64437c26f47424195cdf2a62a8d4c51e4af791bb48da8f5b7ee6c9", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "cf40d5a1fe49a9016205cfe8765f21e7b515adcd26343246e4124d9f73428a1f", - "start_line": 648, - "name": "compare_host?", - "arity": 2 - }, - "compare_host?/2:645": { - "line": 645, - "guard": null, - "pattern": "request_host, <<\"*.\"::binary, allowed_host::binary>>", - "kind": "defp", - "end_line": 646, - "ast_sha": "f41c3112509cae8d96a60c40cf60a61ab87adeee09051dbec3ec5ffb0a8702ee", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "66e5d228db7fb86029a5e2d717dff97c5468a30a91005fb20aa15e05d84ac105", - "start_line": 645, - "name": "compare_host?", - "arity": 2 - }, - "origin_allowed?/4:622": { - "line": 622, - "guard": null, - "pattern": "true, uri, endpoint, _conn", - "kind": "defp", - "end_line": 623, - "ast_sha": "20a92fff970104588887219e8651f4ac61b64af9c139b75f46593056d35e84a2", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "11db20408a9b0b03ec7f02dd2e0840a8d27b27e9fe47fb12cc5fab7bf0871980", - "start_line": 622, - "name": "origin_allowed?", - "arity": 4 - }, - "check_subprotocols/2:400": { - "line": 400, - "guard": null, - "pattern": "conn, nil", - "kind": "def", - "end_line": 400, - "ast_sha": "4e8519273addb0b1417c32122610eed910e40f389be8aeb024763d6e567589c2", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "cd5308f68c5729e611c14b3aa93c46ef05289574c38c4dacf6b5b7965fd14c97", - "start_line": 400, - "name": "check_subprotocols", - "arity": 2 - }, - "origin_allowed?/4:613": { - "line": 613, - "guard": null, - "pattern": ":conn, uri, _endpoint, %Plug.Conn{} = conn", - "kind": "defp", - "end_line": 616, - "ast_sha": "389155eba67dfdba850d0fe8ee59e9429a3da3b48debc9088f6ece013f71b812", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "8439c719340bc89105fcea77c202b83829251bdc79d76718be28cc59e8b6f5c9", - "start_line": 613, - "name": "origin_allowed?", - "arity": 4 - }, - "check_origin/5:343": { - "line": 343, - "guard": null, - "pattern": "conn, handler, endpoint, opts, sender", - "kind": "def", - "end_line": 382, - "ast_sha": "6fe1ac0d839051aaa1b17aa1a4b4ae6eea3a3a28be9fdad734c891e326e336a6", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "bf0de1ae84e6f7df8ce36fd4d3e6db979d341c198a426f8afa37c9a47e8880b1", - "start_line": 343, - "name": "check_origin", - "arity": 5 - }, - "compare?/2:638": { - "line": 638, - "guard": null, - "pattern": "request_val, allowed_val", - "kind": "defp", - "end_line": 639, - "ast_sha": "c56ff87d620f5ad6877a1a6995d8e51afe209f898e820421e277f28d8ead48bf", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "2c46c93aa5ee4b75f9a65034b84e9528f0eeeb30ec0a2b884a60e33f205a1f1f", - "start_line": 638, - "name": "compare?", - "arity": 2 - }, - "compare_host?/2:642": { - "line": 642, - "guard": null, - "pattern": "_request_host, nil", - "kind": "defp", - "end_line": 642, - "ast_sha": "9e8d178a9777dfd5b4870c16eb1fc2c1a94f10cf4686bdd1d0de611ee92113ef", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "af789848da0449c38a3ce4e4179c493214798ea0bdba17edb3c06325e1fe2c24", - "start_line": 642, - "name": "compare_host?", - "arity": 2 - }, - "init_session/1:292": { - "line": 292, - "guard": "is_list(session_config)", - "pattern": "session_config", - "kind": "defp", - "end_line": 297, - "ast_sha": "30f42eac4425e7013216fb85ebdc91123553e9c54cd696b8e26ad9a835ac92c9", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "646a0dd8551cdaf0ef833b9e3cf1aca0796e73cd55d4ab9a5329aad57544ca48", - "start_line": 292, - "name": "init_session", - "arity": 1 - }, - "fetch_uri/1:547": { - "line": 547, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 554, - "ast_sha": "bba0a8cd573a6d0514be967ffee3cfb7e4183a00eee65760a8511b783a94d470", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "8f3916e4281a2aa3370bd6fc6db24e95805a7a5f5c91a53c8b66069726ef6f73", - "start_line": 547, - "name": "fetch_uri", - "arity": 1 - }, - "connect_info/3:477": { - "line": 477, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 477, - "ast_sha": "544e2ebb11b86ce0e5d1a56aadc21cb40acb30fcfbda40659d1563136894c12b", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "d801c426349759d1544157df02a36ae6cb43698506e29f81fb325ec64934f844", - "start_line": 477, - "name": "connect_info", - "arity": 3 - }, - "check_subprotocols/2:402": { - "line": 402, - "guard": "is_list(subprotocols)", - "pattern": "conn, subprotocols", - "kind": "def", - "end_line": 416, - "ast_sha": "8ea3a28b04460eb3ec9569d12ab20c8174c97d4fe0c756b13d09b894d6b37898", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "b176bbaee68abad8160ad63261f367404e3d3506beab030a479630a8a940a05c", - "start_line": 402, - "name": "check_subprotocols", - "arity": 2 - }, - "subprotocols_error_response/2:423": { - "line": 423, - "guard": null, - "pattern": "conn, subprotocols", - "kind": "defp", - "end_line": 451, - "ast_sha": "d2cd671a0e1e28853ee41f4d308d050adc618b1b583e8341413e449b2f6e24a1", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "e13fa61d93c37deef9a24b1a1909ebb05bd3998232c81d20953c63911dfa464a", - "start_line": 423, - "name": "subprotocols_error_response", - "arity": 2 - }, - "origin_allowed?/4:625": { - "line": 625, - "guard": "is_list(check_origin)", - "pattern": "check_origin, uri, _endpoint, _conn", - "kind": "defp", - "end_line": 626, - "ast_sha": "97cc44042ae0b4ba7dca73f2a23268ec62405888e06fbfae2206b7cc1c9fd17a", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "b4894134157716de6ae61a3ee585e0fafdaac54eeb36e5fc4f7c5cbac7e0d292", - "start_line": 625, - "name": "origin_allowed?", - "arity": 4 - }, - "check_origin/4:338": { - "line": 338, - "guard": null, - "pattern": "x0, x1, x2, x3", - "kind": "def", - "end_line": 338, - "ast_sha": "8d672323f6bae716c1211565ab9f7775dc8dd23d6771f92d1adb5c0efd594481", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "4d3c5ed3099b11c66cdab5bb859d903c7f61161dc78af783391f810ff83197ba", - "start_line": 338, - "name": "check_origin", - "arity": 4 - }, - "init_session/1:300": { - "line": 300, - "guard": null, - "pattern": "{_, _, _} = mfa", - "kind": "defp", - "end_line": 301, - "ast_sha": "5e77b62f89f20aebd0f53e49b407167057a12828c38456bf8328bfb9be867f99", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "888d7fd6c9da4969a337b58dcb7a3200eedb25a53c4bc03991006feed6cccbf7", - "start_line": 300, - "name": "init_session", - "arity": 1 - }, - "host_to_binary/1:653": { - "line": 653, - "guard": null, - "pattern": "host", - "kind": "defp", - "end_line": 653, - "ast_sha": "fcc6e42a3178691cc48b853962a3394fe692fb40382672cd3ed333809f8bfc0e", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "5c1f211fed7786a4ce62803ec43b1ba6368132b8316e3013254c6cb6acf4d2dd", - "start_line": 653, - "name": "host_to_binary", - "arity": 1 - }, - "transport_log/2:320": { - "line": 320, - "guard": null, - "pattern": "conn, level", - "kind": "def", - "end_line": 324, - "ast_sha": "dd12a6777356764c5c6561ead713b56cf06c887d00e5d6699089e334099bd80d", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "46f17972171c13c890ed60e0cfd21b5cc856b76bbe887f8f8e908596199b189a", - "start_line": 320, - "name": "transport_log", - "arity": 2 - }, - "load_config/1:259": { - "line": 259, - "guard": null, - "pattern": "config", - "kind": "def", - "end_line": 287, - "ast_sha": "745287617380910b8002a8ccbd698e940f77f2125b263d9b0a2d5f6b3ffb95af", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "51aae811929b3114071495ac7a4763940f7be37655f85d49e410e98f7d02e8ba", - "start_line": 259, - "name": "load_config", - "arity": 1 - }, - "origin_allowed?/4:619": { - "line": 619, - "guard": null, - "pattern": "_check_origin, %{host: nil}, _endpoint, _conn", - "kind": "defp", - "end_line": 619, - "ast_sha": "ae5a995df6fadae24ee7dc349bb4b91509f9fedfe5437c19250643bd2250b28a", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "704da459fc1676bae3eaf9083913c5d0dc9e0424a090239e03c315c858651f7a", - "start_line": 619, - "name": "origin_allowed?", - "arity": 4 - }, - "origin_allowed?/2:628": { - "line": 628, - "guard": null, - "pattern": "uri, allowed_origins", - "kind": "defp", - "end_line": 634, - "ast_sha": "c6122dc08b1fd9c0db79cc5e75ecb11a96356a9d5a6540ebe95f2624685915b4", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "8b26b01c2256e8035b44b42ccab4ed0e0992d92f4fa3fa714db623757e26e38c", - "start_line": 628, - "name": "origin_allowed?", - "arity": 2 - }, - "load_config/2:255": { - "line": 255, - "guard": null, - "pattern": "config, module", - "kind": "def", - "end_line": 256, - "ast_sha": "9800d75d24fa40ef97664018362026816c5fb459c0ec1250b978ffee77fdd626", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "4c334732fa4b800cfcecc354d43b65614b15f024159c08a5a62061f92ccf59b5", - "start_line": 255, - "name": "load_config", - "arity": 2 - }, - "connect_info/4:477": { - "line": 477, - "guard": null, - "pattern": "conn, endpoint, keys, opts", - "kind": "def", - "end_line": 505, - "ast_sha": "7541e2b52c13d7886a0d07ffd97b444dde6784e9e303f1693c380c4373153d65", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "da043cf87961fec862b42b365375a064a11d2af31a9eeb74c4cebf58a3234748", - "start_line": 477, - "name": "connect_info", - "arity": 4 - }, - "check_subprotocols/2:421": { - "line": 421, - "guard": null, - "pattern": "conn, subprotocols", - "kind": "def", - "end_line": 421, - "ast_sha": "218ae1a83a1737fa045069d6aaab4b3dbfce77f2b581961b495eff430122b9f9", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "130c0e07053042001b2693472ff93cf9ed9adce9b5ddb03cf92b3c990fb08c53", - "start_line": 421, - "name": "check_subprotocols", - "arity": 2 - }, - "origin_allowed?/4:610": { - "line": 610, - "guard": null, - "pattern": "{module, function, arguments}, uri, _endpoint, _conn", - "kind": "defp", - "end_line": 611, - "ast_sha": "9f06e60b6e38be41e4bb5c3d633a3fccc20818867eb18a5261084a7f6c91f24c", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "773c740f09e92bb019f4a6f5acaa9c864d311383831c0fbbd81a0839049b3db4", - "start_line": 610, - "name": "origin_allowed?", - "arity": 4 - }, - "load_config/2:252": { - "line": 252, - "guard": null, - "pattern": "true, module", - "kind": "def", - "end_line": 253, - "ast_sha": "60d848556f057edda5a0692b7ca606e7232fa7b94ad0866c39af4da1cb59e347", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "78512d45fb4548e8034177a68272804368a6e3a61e93ea97c98ad7da02f72cea", - "start_line": 252, - "name": "load_config", - "arity": 2 - }, - "fetch_trace_context_headers/1:541": { - "line": 541, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 544, - "ast_sha": "6155d2457023cee8d122814130421699840a8e1fbf776267378b1124c5b17bba", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "9d559a8291be8b8b0e111bc1e7fb4995b5b65c3f679079e668fc6427bea55519", - "start_line": 541, - "name": "fetch_trace_context_headers", - "arity": 1 - }, - "code_reload/3:307": { - "line": 307, - "guard": null, - "pattern": "conn, endpoint, opts", - "kind": "def", - "end_line": 312, - "ast_sha": "62d4188b0ff7f4cf42012e4d8c08f1236d029ead81bf393508e4aa780cfba38d", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "c2d8fb5c279337e3a3d4d7c30c9614b0a7d92f9c75ac5b607169f572bcc29212", - "start_line": 307, - "name": "code_reload", - "arity": 3 - }, - "connect_session/4:524": { - "line": 524, - "guard": null, - "pattern": "conn, endpoint, {:mfa, {module, function, args}}, opts", - "kind": "defp", - "end_line": 531, - "ast_sha": "e103c3ba223e9962976286fcd01aacffd1ba11dedbd41d3003630dc08aaabb39", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "cd5bc0ecbba54c0d6e795bc30794115f9ad35d464bd68acb87233b7e168cd2b9", - "start_line": 524, - "name": "connect_session", - "arity": 4 - }, - "connect_session/4:510": { - "line": 510, - "guard": null, - "pattern": "conn, endpoint, {key, store, {csrf_token_key, init}}, opts", - "kind": "defp", - "end_line": 520, - "ast_sha": "7b3d5c04a4aac63c97c52c7acc7bd7f92952aa0e4d2795f7219972a5d064ab95", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "efb1f135bcd631272821c2df257bd49c6d6156ae89082f647be2ceb170363032", - "start_line": 510, - "name": "connect_session", - "arity": 4 - }, - "fetch_user_agent/1:558": { - "line": 558, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 560, - "ast_sha": "552e3109fbd70f9decc237c97fdfa0133aa9e7b0d97fb24f3142f168494ad000", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "a295ddb4a7c24682d8bbd29370279b1785d1e9c41e099e98edab2ef9b1bada69", - "start_line": 558, - "name": "fetch_user_agent", - "arity": 1 - }, - "check_origin/5:340": { - "line": 340, - "guard": null, - "pattern": "%Plug.Conn{halted: true} = conn, _handler, _endpoint, _opts, _sender", - "kind": "def", - "end_line": 341, - "ast_sha": "b563ead2a4fcb1b4a890ec6da951408fbc3eca4f6422c7b8d7a317dfb17058e9", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "548d598cf4ba8607fb3ce0b5acea632cfb789e93bee3d401d5b91b77b5258c99", - "start_line": 340, - "name": "check_origin", - "arity": 5 - }, - "parse_origin/1:597": { - "line": 597, - "guard": null, - "pattern": "origin", - "kind": "defp", - "end_line": 606, - "ast_sha": "416f2269f24300d7a69076c23b10cfbcfba4ca041ca897f0ffaf5a9879a36d9f", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "856f9e7d6decfdd23c29af2e23e4f234ada402e3b5af5f23a5e69d379c742024", - "start_line": 597, - "name": "parse_origin", - "arity": 1 - }, - "check_origin_config/3:572": { - "line": 572, - "guard": null, - "pattern": "handler, endpoint, opts", - "kind": "defp", - "end_line": 593, - "ast_sha": "5b4e2777dbdcb7d894048b5aed3de7bad672c412c3f9bcc78f2fff5d641662cb", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "1db8bc7007747848232b3649a32aee48001b2410fd3096b4e0d824940123fdff", - "start_line": 572, - "name": "check_origin_config", - "arity": 3 - }, - "csrf_token_valid?/3:564": { - "line": 564, - "guard": null, - "pattern": "conn, session, csrf_token_key", - "kind": "defp", - "end_line": 568, - "ast_sha": "f9b3321f88a93ac67c0cdb5fca03436f060bcaa310a49c7ae171e154b801ee0b", - "source_file": "lib/phoenix/socket/transport.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/transport.ex", - "source_sha": "2e13cea734b0b26f6c9e36faa6e216dd1ff8aef2ae3a667e6139e008c806dc17", - "start_line": 564, - "name": "csrf_token_valid?", - "arity": 3 - } - }, - "Phoenix.Naming": { - "camelize/1:94": { - "line": 94, - "guard": null, - "pattern": "value", - "kind": "def", - "end_line": 94, - "ast_sha": "2c67ece3716533779f0149da8b92bb61a3ff663281e48d645eee71cb62d4e07f", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "dc78a1cbc8f34ee1ee7f2e5ac40e6dcc50f3f559c5063fdfc3a85df1354009c4", - "start_line": 94, - "name": "camelize", - "arity": 1 - }, - "camelize/2:101": { - "line": 101, - "guard": null, - "pattern": "<> = value, :lower", - "kind": "def", - "end_line": 103, - "ast_sha": "e10e1f124d509ef0c50f4f28d03db198c002ac259d9699af99d8b916cef7c5c6", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "1516909d957903ed67970deca4bb7780971580a195d017df558eac18dcc78b9c", - "start_line": 101, - "name": "camelize", - "arity": 2 - }, - "camelize/2:97": { - "line": 97, - "guard": null, - "pattern": "\"\", :lower", - "kind": "def", - "end_line": 97, - "ast_sha": "2ec4c7aec610386230d8b490381e49ec64d75f4825563d1e97ae832c5fd63af8", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "df244ad629d48a289344d51bd1244162e4e284ca186a8c5e853455147edce033", - "start_line": 97, - "name": "camelize", - "arity": 2 - }, - "camelize/2:98": { - "line": 98, - "guard": null, - "pattern": "<<95::integer, t::binary>>, :lower", - "kind": "def", - "end_line": 99, - "ast_sha": "4f63bc9e5817e55e6fa3f4d8782f96de67883fb4bd7eaff1e3fc6f9d2578b5eb", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "d2679a9651234101e6180842c047de38e559ea791ca737e53df4e545be37c42e", - "start_line": 98, - "name": "camelize", - "arity": 2 - }, - "humanize/1:120": { - "line": 120, - "guard": "is_atom(atom)", - "pattern": "atom", - "kind": "def", - "end_line": 121, - "ast_sha": "182de8b4cb2d826c22ed408988844c0a06d601bd747c27ebabad53ea7bea27a1", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "4aec0d487e52a042a46fa0b7d67a65780ad1df743ad18e27f891fca639ccff45", - "start_line": 120, - "name": "humanize", - "arity": 1 - }, - "humanize/1:122": { - "line": 122, - "guard": "is_binary(bin)", - "pattern": "bin", - "kind": "def", - "end_line": 130, - "ast_sha": "a1ad241b08faca2fe25140c7e9aa83242cd91191759108fb8c543f4e4daa92bd", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "4f1c48e5d706272b6364b184fd248de50eaaeb5a55cb669ae67ff2bce2802b18", - "start_line": 122, - "name": "humanize", - "arity": 1 - }, - "resource_name/1:19": { - "line": 19, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 19, - "ast_sha": "7ba94cbf74fd9d39aa9fe5db0ccdd419392af9907b9581646f3539cede68feba", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "1c1b421623ed779226b0e901b4ce7585e2855f389010e04d3e3ad6b5f3dd48ee", - "start_line": 19, - "name": "resource_name", - "arity": 1 - }, - "resource_name/2:19": { - "line": 19, - "guard": null, - "pattern": "alias, suffix", - "kind": "def", - "end_line": 25, - "ast_sha": "73e920149d7868c1d5de382022468cf8be731f5e286dfe3da20f7a7282878ee3", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "fe74c20a82790ff7a0a9a3be3eac8b70a2614ea4fda02997b1b54e4d9f4d69c8", - "start_line": 19, - "name": "resource_name", - "arity": 2 - }, - "to_lower_char/1:70": { - "line": 70, - "guard": "is_integer(char) and (char >= 65 and =<(char, 90))", - "pattern": "char", - "kind": "defp", - "end_line": 70, - "ast_sha": "996452a895e12e0cccc9eea1f3b301e0daaffc23f0fda342acdb7372e755b1b7", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "becafab6095ee9a45a665b8790370ab0d27b5ba5659b927c4a9bfd10ef915492", - "start_line": 70, - "name": "to_lower_char", - "arity": 1 - }, - "to_lower_char/1:71": { - "line": 71, - "guard": null, - "pattern": "char", - "kind": "defp", - "end_line": 71, - "ast_sha": "3989282711c9818c42279b7e9fc7c3b3a0f5f7b6021dd8c838e4cdd026d654af", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "b3c8dbce9298d8ef976a69d435bd06cea652d2423d5246e239ef2d4202db9d51", - "start_line": 71, - "name": "to_lower_char", - "arity": 1 - }, - "underscore/1:68": { - "line": 68, - "guard": null, - "pattern": "value", - "kind": "def", - "end_line": 68, - "ast_sha": "bd0aaf69044896c42ad2b5f0ecf97214dfad9a6da1ec935b80d65d87248fd7e2", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "c3f5d6a0ab8f8a34a2c5da36b2c81e4df91a298b2c1c0ab3c91ff7dce9493723", - "start_line": 68, - "name": "underscore", - "arity": 1 - }, - "unsuffix/2:41": { - "line": 41, - "guard": null, - "pattern": "value, suffix", - "kind": "def", - "end_line": 47, - "ast_sha": "e6eea8b052555b4dd3585508606412044d8add5de969e31e78f5ec35d05e120b", - "source_file": "lib/phoenix/naming.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/naming.ex", - "source_sha": "7908c11e270ff6df52f32bb5b3a7908d6c2a87bf61cfcc3c3e7dbaa6aedd92a2", - "start_line": 41, - "name": "unsuffix", - "arity": 2 - } - }, - "Phoenix.Flash": { - "get/2:16": { - "line": 16, - "guard": "is_atom(key) or is_binary(key)", - "pattern": "%mod{}, key", - "kind": "def", - "end_line": 22, - "ast_sha": "b0aeb44ea14cb6fffdfd0b54b6e4e77c157d84e2d63d2b1fee1d8ec9d7fdc92e", - "source_file": "lib/phoenix/flash.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/flash.ex", - "source_sha": "8c366e1fa2d3ab4ddca56bcfbecabae698cc0e33e15d0b45bab6f94d9372762b", - "start_line": 16, - "name": "get", - "arity": 2 - }, - "get/2:26": { - "line": 26, - "guard": "is_atom(key) or is_binary(key)", - "pattern": "%{} = flash, key", - "kind": "def", - "end_line": 27, - "ast_sha": "834ef518fb6551b5ede0268289f963c35c9f279a41c28636c3c418bd2c28de59", - "source_file": "lib/phoenix/flash.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/flash.ex", - "source_sha": "18da48c08c298e1ccc90a211e90b470e806175c7b2e22dc61068d2912bcbe19d", - "start_line": 26, - "name": "get", - "arity": 2 - } - }, - "Phoenix.Param": { - "__protocol__/1:1": { - "line": 1, - "guard": null, - "pattern": ":impls", - "kind": "def", - "end_line": 1, - "ast_sha": "4f1c606279ac67edd5528d121f2659b413d16a80d813d2f05a25033ac26c3f4d", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", - "start_line": 1, - "name": "__protocol__", - "arity": 1 - }, - "impl_for!/1:1": { - "line": 1, - "guard": null, - "pattern": "data", - "kind": "def", - "end_line": 1, - "ast_sha": "0129afca6d596b23db35947e4691e4dd75099b4c0c61622fd97605507956c79c", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", - "start_line": 1, - "name": "impl_for!", - "arity": 1 - }, - "impl_for/1:1": { - "line": 1, - "guard": null, - "pattern": "_", - "kind": "def", - "end_line": 1, - "ast_sha": "e6a47c766d4b1bfb12ea57a07a83017d7400497e63a53cc18e30992e2723fb3a", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", - "start_line": 1, - "name": "impl_for", - "arity": 1 - }, - "struct_impl_for/1:1": { - "line": 1, - "guard": null, - "pattern": "struct", - "kind": "defp", - "end_line": 1, - "ast_sha": "e241871f23063a938abbfb27c236c7ae3ad09bfb5054c8ce1d1f7b30ec66365e", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "7580dfe2484d0b7202cb2f30818aa47fcedf2f2d365cefafd8409a8009b564d1", - "start_line": 1, - "name": "struct_impl_for", - "arity": 1 - }, - "to_param/1:63": { - "line": 63, - "guard": null, - "pattern": "term", - "kind": "def", - "end_line": 63, - "ast_sha": "2598a950a2228266ac63b4e46ab6adb46472e140472ecb5cc3a8b31cd87d68d5", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "9ac9cf4a8c26dc07338a7c844baed12437ec3380cc7ed2a0115b428241c5c382", - "start_line": 63, - "name": "to_param", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen": { - "run/1:49": { - "line": 49, - "guard": null, - "pattern": "_args", - "kind": "def", - "end_line": 50, - "ast_sha": "09356baf05294a1be4d877b6c89c4f02a5d1133061e988d85973923b1d575371", - "source_file": "lib/mix/tasks/phx.gen.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.ex", - "source_sha": "c15bf928d21a70e41c36b29243761f967c77d12f5fc629a100e10f2d447e1b4c", - "start_line": 49, - "name": "run", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Embedded": { - "build/1:54": { - "line": 54, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 64, - "ast_sha": "ba1d55ebc6b3d9f623a463445f77e9c0a64ef0d09d680466ff3f2ff2e2ffc7be", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "958cab6226e45a37bba006b87db4de9f6653766d4b6651c0fd16a9ffc61da35b", - "start_line": 54, - "name": "build", - "arity": 1 - }, - "copy_new_files/3:105": { - "line": 105, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema, paths, binding", - "kind": "def", - "end_line": 109, - "ast_sha": "19af7128a56afb86e51066fa64063a4bb45e74b184499c239a9de9f0bafecb85", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "d278c70c9e5de696f9882f5c900a7b9054104b6213a65f85634004754ffd94e6", - "start_line": 105, - "name": "copy_new_files", - "arity": 3 - }, - "files_to_be_generated/1:100": { - "line": 100, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema", - "kind": "def", - "end_line": 101, - "ast_sha": "836c5e229c14c7b49397e5a11aae1bfaf230d374a132b88e9ec730210dff5a7d", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "edbb0e972769fbcc789fc74f8247631001db67234f2237cae70cf43d5387afd6", - "start_line": 100, - "name": "files_to_be_generated", - "arity": 1 - }, - "prompt_for_conflicts/1:93": { - "line": 93, - "guard": null, - "pattern": "schema", - "kind": "defp", - "end_line": 96, - "ast_sha": "f3ebba6f09507aaafdbfebf320f772d0f8a85751ac25e7bb4a01a2dadf970f7b", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "bee6f3131373fd7506ad81096775ca9a4d421535f9688f8619f6d4381712a0cd", - "start_line": 93, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "raise_with_help/1:81": { - "line": 81, - "guard": null, - "pattern": "msg", - "kind": "def", - "end_line": 83, - "ast_sha": "e64ca138101be4986f932fc66c2bec82da0a921cb180891af3c18c38dcd2e144", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "a09cec29e86945790f3d97ae21f6380d7295082ac65114a4fac62e0c84b662f0", - "start_line": 81, - "name": "raise_with_help", - "arity": 1 - }, - "run/1:39": { - "line": 39, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 50, - "ast_sha": "82d90884242784f4074e34dd2054497639a73fc86bfd59efddd1dd0763fc1869", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "c92192d1481ce8db7a46d9a0ba67cbc391fac4b1b94f90e3da7ba20cafab64d9", - "start_line": 39, - "name": "run", - "arity": 1 - }, - "validate_args!/1:68": { - "line": 68, - "guard": null, - "pattern": "[schema | _] = args", - "kind": "def", - "end_line": 72, - "ast_sha": "c22fd59fc81eedd53a90d926305e42635083cbe285e46499d85e1507baae347b", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "c895a6096eafa7e32142ff3a73cfacc6129343f10e8bc7b992e9d5dfdf2f437c", - "start_line": 68, - "name": "validate_args!", - "arity": 1 - }, - "validate_args!/1:75": { - "line": 75, - "guard": null, - "pattern": "_", - "kind": "def", - "end_line": 76, - "ast_sha": "ea8e3213d2e54dd0152e93e9d31ecdc162de6b86b60c8a0edae5839f7ef68933", - "source_file": "lib/mix/tasks/phx.gen.embedded.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.embedded.ex", - "source_sha": "dada4dc83d81ccf2c8901374f7ac8482dcc8ed608e3f8f0dc5e5a64a3ac2a7b9", - "start_line": 75, - "name": "validate_args!", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Schema": { - "build/2:188": { - "line": 188, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 188, - "ast_sha": "4c476677119535391ce3657187afb1fc11a8ef238dc4096942743c366b3e25b6", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "059590d05ac4e593e27132e46d6d35958104ef18dad69b7a7c38281381137ed5", - "start_line": 188, - "name": "build", - "arity": 2 - }, - "build/3:188": { - "line": 188, - "guard": null, - "pattern": "args, parent_opts, help", - "kind": "def", - "end_line": 198, - "ast_sha": "c555515f5dd22ff5d98576a91000c8739a5e16a63d2f1370cbd97c127b7c42a9", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "f5b3f20d0e16d1877f0258536dc3689eb601b36958ed3d96755b52052373b05f", - "start_line": 188, - "name": "build", - "arity": 3 - }, - "copy_new_files/3:220": { - "line": 220, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{context_app: ctx_app, repo: repo, opts: opts} = schema, paths, binding", - "kind": "def", - "end_line": 245, - "ast_sha": "5d80d6ab9a58f5245a638641b98b42c0cf9ece6d4e77c03258da0618df84ec06", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "71086fd0922bb40cacc34c65a5423421372a4810a1911d6dd344242dff70a278", - "start_line": 220, - "name": "copy_new_files", - "arity": 3 - }, - "files_to_be_generated/1:215": { - "line": 215, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema", - "kind": "def", - "end_line": 216, - "ast_sha": "cfc61e405b012b62ae1290b7ddcb9b0b2fa2936c2d72b0f3ae756aeaa4ff22f1", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "941753b1e208bcafc57e1e93109eb3d693aa01345de09e4d229db4c482181788", - "start_line": 215, - "name": "files_to_be_generated", - "arity": 1 - }, - "maybe_update_repo_module/1:201": { - "line": 201, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 205, - "ast_sha": "ae1c709db1f407c414cef02a3bb6434c7d3ad8054c79e129b4cee036759fd727", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "526da3ca8ee524307dc95781a0af32a97f1121b1031116571ceb1a67f4514e33", - "start_line": 201, - "name": "maybe_update_repo_module", - "arity": 1 - }, - "pad/1:293": { - "line": 293, - "guard": "i < 10", - "pattern": "i", - "kind": "defp", - "end_line": 293, - "ast_sha": "8b589203e40ca35f83ec568fa85e008e7480f94a3d60e205b97c1343c4825ef2", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "73e7c06a9aa90212051bbd282f6e51e4e419e2e8968cea8ff13c37b5ae90a7de", - "start_line": 293, - "name": "pad", - "arity": 1 - }, - "pad/1:294": { - "line": 294, - "guard": null, - "pattern": "i", - "kind": "defp", - "end_line": 294, - "ast_sha": "7613e3e1bfe1c748170999bc1e64e19cbf322d289f35b52b80799f06fdcdf962", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "019ee63a3ac952acdb672c9b9c381889dbecd8c4fea6d62ffa991c27316520a9", - "start_line": 294, - "name": "pad", - "arity": 1 - }, - "print_shell_instructions/1:249": { - "line": 249, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema", - "kind": "def", - "end_line": 251, - "ast_sha": "e16cae37adb87df05c7040914693eb9b83ba4e59b6e4178a0b03d90acf2a1ecc", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "475717ced8a410a8647dd6aa6ce294bbacf9ab127073bd6c4116c9c44c51a5f8", - "start_line": 249, - "name": "print_shell_instructions", - "arity": 1 - }, - "prompt_for_conflicts/1:181": { - "line": 181, - "guard": null, - "pattern": "schema", - "kind": "defp", - "end_line": 184, - "ast_sha": "4ebed16af1090fd3b1fde82d10f0bbf870965463cb9125dcc7a9404cd5b56fcc", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "bee6f3131373fd7506ad81096775ca9a4d421535f9688f8619f6d4381712a0cd", - "start_line": 181, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "put_context_app/2:209": { - "line": 209, - "guard": null, - "pattern": "opts, nil", - "kind": "defp", - "end_line": 209, - "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", - "start_line": 209, - "name": "put_context_app", - "arity": 2 - }, - "put_context_app/2:210": { - "line": 210, - "guard": null, - "pattern": "opts, string", - "kind": "defp", - "end_line": 211, - "ast_sha": "97852ff283af0b58617a4a93d1e8a5d6859c264009a967a7b9a53e1bde5f434e", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", - "start_line": 210, - "name": "put_context_app", - "arity": 2 - }, - "raise_with_help/1:277": { - "line": 277, - "guard": null, - "pattern": "msg", - "kind": "def", - "end_line": 279, - "ast_sha": "df89099af45bf6da77884d80f6722f5fae62099f175bbacf21807a11f05ac2d4", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "a09cec29e86945790f3d97ae21f6380d7295082ac65114a4fac62e0c84b662f0", - "start_line": 277, - "name": "raise_with_help", - "arity": 1 - }, - "run/1:160": { - "line": 160, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 178, - "ast_sha": "35499c54af4ea0f7661dc243c49872adbafb0e4981e975acd2b48195c63ae3c8", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "87f110bdd959f277b81da4a1afc2e088156296a5ab44853f3cf0c49f6e9a5688", - "start_line": 160, - "name": "run", - "arity": 1 - }, - "timestamp/0:289": { - "line": 289, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 291, - "ast_sha": "3a10e0a2a76a5ce3100206ac91d09baa3d18d8c8895707311d5d55da99823cde", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "31815f67847bad4ae7aa82b79514b445b4ddd807b20356094669e72b46c33894", - "start_line": 289, - "name": "timestamp", - "arity": 0 - }, - "validate_args!/2:261": { - "line": 261, - "guard": null, - "pattern": "[schema, plural | _] = args, help", - "kind": "def", - "end_line": 268, - "ast_sha": "b8050d7b02dfcca9a813bcf300c9d29188f339b597e72418e1e91a54b5f656e1", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "9bba4cfc54ed93fb05eff613a8fcad46bed684c1172b01b54984e38c0ae67ea5", - "start_line": 261, - "name": "validate_args!", - "arity": 2 - }, - "validate_args!/2:271": { - "line": 271, - "guard": null, - "pattern": "_, help", - "kind": "def", - "end_line": 272, - "ast_sha": "e8e342b85119228478b2020aa721f7ca5c106a5731f706e99036f2f4db1e446a", - "source_file": "lib/mix/tasks/phx.gen.schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.schema.ex", - "source_sha": "3384137ada961cb108dfda84f5d6264762adfed431234cd8e9bffdf30b5c54f2", - "start_line": 271, - "name": "validate_args!", - "arity": 2 - } - }, - "Mix.Tasks.Phx.Digest": { - "run/1:58": { - "line": 58, - "guard": null, - "pattern": "all_args", - "kind": "def", - "end_line": 85, - "ast_sha": "b1009a0ce1ba7e8e15904d3da3e67f48dab1d6f4179ee1dfb061a55a528e5c54", - "source_file": "lib/mix/tasks/phx.digest.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.ex", - "source_sha": "3837a610c3f149cc2fbd4d826321ac926acefc84556d656d67a8305b80019dc1", - "start_line": 58, - "name": "run", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Html": { - "context_files/1:182": { - "line": 182, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: true} = context", - "kind": "defp", - "end_line": 183, - "ast_sha": "3f1f5773a352652e98659f95d64b39dea06e4606844dbae5bc76b31b3ac4cbc4", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", - "start_line": 182, - "name": "context_files", - "arity": 1 - }, - "context_files/1:186": { - "line": 186, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: false}", - "kind": "defp", - "end_line": 186, - "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", - "start_line": 186, - "name": "context_files", - "arity": 1 - }, - "copy_new_files/3:214": { - "line": 214, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", - "kind": "def", - "end_line": 218, - "ast_sha": "f33b6533a0580ef203ef23df185ac0e92de30ab96c5248eedc2320f959fe6f38", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "7849e380c3390159929d45e0fd3a4e91f293e7bdfbc8803742039da22a9b2539", - "start_line": 214, - "name": "copy_new_files", - "arity": 3 - }, - "default_options/1:318": { - "line": 318, - "guard": null, - "pattern": "{:array, :string}", - "kind": "defp", - "end_line": 319, - "ast_sha": "f58fab999b05901f2765f36488b54452e476ac6c67a344c0eaab8c8928b06a0b", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "f7baf8656ec69550ba797003cef4dbce49c50ef0b06cbbde34d1c7ec4a169d69", - "start_line": 318, - "name": "default_options", - "arity": 1 - }, - "default_options/1:321": { - "line": 321, - "guard": null, - "pattern": "{:array, :integer}", - "kind": "defp", - "end_line": 322, - "ast_sha": "fc71b3d0d379e7a4363968ae1542322b57144517a9a54f3590405eb6d3db3d7e", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "0c6bc5b7c2583cc53321531782442ea51cc59459c6217490af281d5912293cc3", - "start_line": 321, - "name": "default_options", - "arity": 1 - }, - "default_options/1:324": { - "line": 324, - "guard": null, - "pattern": "{:array, _}", - "kind": "defp", - "end_line": 324, - "ast_sha": "5d58293c50e5eb42c1fc4cac63844c442b64a79f7acb29119153166f52272db3", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "71475429cbe803cbdb6e7877819a8eb755b00b60d50eb7ad2408348c028d0ed0", - "start_line": 324, - "name": "default_options", - "arity": 1 - }, - "files_to_be_generated/1:191": { - "line": 191, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", - "kind": "def", - "end_line": 209, - "ast_sha": "8c2ab806806bba9b57ad0a95960e04a40f80750d31a4444840d574a09a3dab98", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "563f7bec5dbff34c327bd9faddedcdae3796cbed1fc66ef5daf4564c235af53c", - "start_line": 191, - "name": "files_to_be_generated", - "arity": 1 - }, - "indent_inputs/2:338": { - "line": 338, - "guard": null, - "pattern": "inputs, column_padding", - "kind": "def", - "end_line": 357, - "ast_sha": "4a53ac8e47d3856e849f74b12ce5bc0c18ce39612119ab8a91a55a371a581b1e", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "4bd69ad1b26ddea5eb3c2bdd20d1c87488ea5c485be2fef1a513549503b8fea8", - "start_line": 338, - "name": "indent_inputs", - "arity": 2 - }, - "inputs/1:260": { - "line": 260, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema", - "kind": "def", - "end_line": 314, - "ast_sha": "1c2a7874fcf2363701ff587ff80ebe36bf3571854c6d50f874f8262e23a7a47a", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "e108fa35154f63ec4892da9d8f780ca433a1695b9b9338cb70076effd0eebdb5", - "start_line": 260, - "name": "inputs", - "arity": 1 - }, - "label/1:326": { - "line": 326, - "guard": null, - "pattern": "key", - "kind": "defp", - "end_line": 326, - "ast_sha": "d44770f4330ec470ee629dbfa2f03dd77c005af0b2a0a8007b4aa09788b57e6d", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "a298472558e596e1e6ef15fbde1f3acc423119bdc3f18e26b72461c14e3fb8ac", - "start_line": 326, - "name": "label", - "arity": 1 - }, - "print_shell_instructions/1:222": { - "line": 222, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", - "kind": "def", - "end_line": 256, - "ast_sha": "b7b0efec8eeac0019a67f43b8ea8106b96eb968b6b88444b862e55a53133de0e", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "a194e9344c78f1e05c312348a35f2b5b8ae8eb632c2035352d1f2a03eed6dcda", - "start_line": 222, - "name": "print_shell_instructions", - "arity": 1 - }, - "prompt_for_conflicts/1:175": { - "line": 175, - "guard": null, - "pattern": "context", - "kind": "defp", - "end_line": 179, - "ast_sha": "817f32e3f8e5f8587beaebb8d0fd678ebd42bebbab256e0c7eafd67ddd3d1a5d", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "90bb78b802f638a452de361d55b4ad7f730fbc458b81fbed27efc49236a0c1d1", - "start_line": 175, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "run/1:121": { - "line": 121, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 172, - "ast_sha": "38184ce305cf79906745d52979f4f1ca8a3b12de614be9299f22a2abe8e85557", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "808ab010e65c1112e2bab808c9c3d963a1acbd0c01f8007efead8367b6476786", - "start_line": 121, - "name": "run", - "arity": 1 - }, - "scope_assign_route_prefix/1:328": { - "line": 328, - "guard": "not (route_prefix == nil)", - "pattern": "%{scope: %{route_prefix: route_prefix, assign_key: assign_key}} = schema", - "kind": "defp", - "end_line": 332, - "ast_sha": "48ed39cfa0e90789389256cca1c0047a9055b9d735811ef29f42295b1ae1ffba", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "247e983a0169c88f62cf9b99c16687f4771d0a3659a130b699eb8f10bd06326e", - "start_line": 328, - "name": "scope_assign_route_prefix", - "arity": 1 - }, - "scope_assign_route_prefix/1:335": { - "line": 335, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 335, - "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", - "source_file": "lib/mix/tasks/phx.gen.html.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.html.ex", - "source_sha": "e9a8e972479e20da74d9b8d9fdd7cc2007152cc11ee0fa7b7a4a1cc6cfadb0e4", - "start_line": 335, - "name": "scope_assign_route_prefix", - "arity": 1 - } - }, - "Phoenix.Param.Integer": { - "__impl__/1:66": { - "line": 66, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 66, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "b045dc19c4eaaae208f712a98cb2e5b0c97805619f103ab499ace1bffb01394e", - "start_line": 66, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:67": { - "line": 67, - "guard": null, - "pattern": "int", - "kind": "def", - "end_line": 67, - "ast_sha": "7a9ee61c9acab3d0d252dbf4c1efbb76ef4a070d8a469f687147b435df4f7db5", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "5189fe06905ea550f6dedd6c94222706855a297c098354b920391fc9b589d978", - "start_line": 67, - "name": "to_param", - "arity": 1 - } - }, - "Phoenix.Endpoint": { - "__before_compile__/1:644": { - "line": 644, - "guard": null, - "pattern": "%{module: module}", - "kind": "defmacro", - "end_line": 697, - "ast_sha": "e3a467474470cf6b86f9572c8c375e14fd715adc3cc284446689097c3e515afe", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "b8c4375a53ad3ea9c4b3174d36772942cd63bc1a44b87c0202a988e574ffa57d", - "start_line": 644, - "name": "__before_compile__", - "arity": 1 - }, - "__force_ssl__/2:637": { - "line": 637, - "guard": null, - "pattern": "module, force_ssl", - "kind": "def", - "end_line": 639, - "ast_sha": "f63e4831bd8d9fce961485e3f67a27d70df29479a52ce849821a707293671bdb", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "6236598fede8287c726928ab67de40a9d7239465cd177f9f13ce76d46583e6a0", - "start_line": 637, - "name": "__force_ssl__", - "arity": 2 - }, - "__using__/1:408": { - "line": 408, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 415, - "ast_sha": "ce9fe0e02e86d0c12c749555ff209b988c3a3a8b4129b21c25309e6da7c250bc", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "453282522d21280ff85cc31c883495cef87e769c227b60b862632f5292196bb0", - "start_line": 408, - "name": "__using__", - "arity": 1 - }, - "config/1:419": { - "line": 419, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 421, - "ast_sha": "75a3f312d3642b2b9a6470c3fb2bf46e51534bff132ee3a756e2f767a412b2e6", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "31a176555d882635c20fc83b27f86c6426897983ae36fac6d4db31c933523971", - "start_line": 419, - "name": "config", - "arity": 1 - }, - "instrument/4:1075": { - "line": 1075, - "guard": null, - "pattern": "_endpoint_or_conn_or_socket, _event, _runtime, _fun", - "kind": "defmacro", - "end_line": 1075, - "ast_sha": "0d33445e602fa0b6b4717c35afae371ddfa3ca7f15260aafe9904dfc51c90d42", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "d80627a04617360c9015155d479bcc2e5257cd641ad49214e28bdd699b23b531", - "start_line": 1075, - "name": "instrument", - "arity": 4 - }, - "maybe_validate_keys/2:801": { - "line": 801, - "guard": "is_list(opts)", - "pattern": "opts, keys", - "kind": "defp", - "end_line": 801, - "ast_sha": "e9da1c0481e39274ce847afd2fdf0944f8469519a10d36bc1fa26493eb77dc15", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "b515929ca479fd14d6db68d11b7751f0ff30fa765927104a8edd90684f94931d", - "start_line": 801, - "name": "maybe_validate_keys", - "arity": 2 - }, - "maybe_validate_keys/2:802": { - "line": 802, - "guard": null, - "pattern": "other, _", - "kind": "defp", - "end_line": 802, - "ast_sha": "7dd091a67e628cc9910ccc7e4b138f2e50011099b7214705998b71748c31f110", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "acef49f9f49f5e93751f9ded9c3fd21ae41692b5cca78ced24ee76ac81c86c6f", - "start_line": 802, - "name": "maybe_validate_keys", - "arity": 2 - }, - "plug/0:478": { - "line": 478, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 478, - "ast_sha": "c3a944fbb3742a0201573751bdc647cbc58e28982621a129a0f85606cb237db7", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "dc24171ffc4655cc8a629a6b9f8b9cb14458eff5d73b38616f30ad2ddcf5b60b", - "start_line": 478, - "name": "plug", - "arity": 0 - }, - "pubsub/0:437": { - "line": 437, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 437, - "ast_sha": "e09c8fee249109809da2afa2ff8d3e86b95f6616524d4e7c47ad7a96191733fd", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "c3929478502c3abcf190a2240af55ee4813897ca766c88ce327b81da3f42ee86", - "start_line": 437, - "name": "pubsub", - "arity": 0 - }, - "put_auth_token/2:769": { - "line": 769, - "guard": null, - "pattern": "true, enabled", - "kind": "defp", - "end_line": 769, - "ast_sha": "953938441f9bea9f7c4abd295549faad8562cb1ccce3f785f5b7abef4d1c2787", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "075fd79ca764005e240d2f4547fc92cc006b4ab0b7fb2225e3418d034e2aa31d", - "start_line": 769, - "name": "put_auth_token", - "arity": 2 - }, - "put_auth_token/2:770": { - "line": 770, - "guard": null, - "pattern": "opts, enabled", - "kind": "defp", - "end_line": 770, - "ast_sha": "57b73d8fa0e55a8afb57a475fdc80bc6d0fd5fb9029b5e1b201e2277462ff9d1", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "26ecc1a2c7d1629e2e37fff5318c724b2f575371c8ecb36bd1447f7b9ffe1b85", - "start_line": 770, - "name": "put_auth_token", - "arity": 2 - }, - "server/0:513": { - "line": 513, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 513, - "ast_sha": "94d73bb89c0e11a7d63cf7e5997106ef3a5449fed0e7401d8eaa48afcb0de11e", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "dac259ad275df9144dbd69283855babc5847d3aabbdeaab20c9c5e5914d92e02", - "start_line": 513, - "name": "server", - "arity": 0 - }, - "server?/2:1091": { - "line": 1091, - "guard": "is_atom(otp_app) and is_atom(endpoint)", - "pattern": "otp_app, endpoint", - "kind": "def", - "end_line": 1092, - "ast_sha": "f5ff70268c7e6b6745a8e99929f5884aefd0fdfaf258196de28437bcc4997a81", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "08d442db71d051520b1d1762e1a7b260b3effb1ed2b49ceed719cfb4b3523b02", - "start_line": 1091, - "name": "server?", - "arity": 2 - }, - "socket/2:1065": { - "line": 1065, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 1065, - "ast_sha": "33170dea01f5958d1d85fb840554f73378343e2cfea52bb3d741f884e15e1c95", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "c8d529278b8239feef16e03ca4bb624053266cd929447db4bfb6caefc788a6e6", - "start_line": 1065, - "name": "socket", - "arity": 2 - }, - "socket/3:1065": { - "line": 1065, - "guard": null, - "pattern": "path, module, opts", - "kind": "defmacro", - "end_line": 1069, - "ast_sha": "91f10db91f04214d7d3a31ff8a8d6b650e959579720da4538c589adab38b3e0f", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "28b86f769a41ac97f6cc1a0bd45f9e0c73b096604da5870d17aaa5b8c2398c51", - "start_line": 1065, - "name": "socket", - "arity": 3 - }, - "socket_path/2:772": { - "line": 772, - "guard": null, - "pattern": "path, config", - "kind": "defp", - "end_line": 798, - "ast_sha": "2eb3da613600cfb78c852f3cdec94abbb0a401adce3573704b5e3431a415733a", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "3fc2aa07db99720626350fbdc6a610935bede22c24f3d551271f45ea17237a09", - "start_line": 772, - "name": "socket_path", - "arity": 2 - }, - "socket_paths/4:702": { - "line": 702, - "guard": null, - "pattern": "endpoint, path, socket, opts", - "kind": "defp", - "end_line": 766, - "ast_sha": "8284953e0d90242d88679f310ee8ec836646be85fbbd4459f2eb6462f37c209d", - "source_file": "lib/phoenix/endpoint.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint.ex", - "source_sha": "88647afc72e344875d4d7885ed8cf78d07923a84f822bdc6010b6c31c3946c78", - "start_line": 702, - "name": "socket_paths", - "arity": 4 - } - }, - "Phoenix.CodeReloader.Server": { - "with_build_lock/1:450": { - "line": 450, - "guard": null, - "pattern": "fun", - "kind": "defp", - "end_line": 450, - "ast_sha": "ba1934804ce69336c0fd10e5bdf9aa9dfebb0d4c9d6b9bc4df575e5db3eced33", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "eb927730aa7f9621cfa53ed22a9fe0d05a64da410b3cabf1a3c883845060652e", - "start_line": 450, - "name": "with_build_lock", - "arity": 1 - }, - "read_backup/1:166": { - "line": 166, - "guard": "is_list(path)", - "pattern": "path", - "kind": "defp", - "end_line": 169, - "ast_sha": "ec2f0bbeaae03c81d102fe7b0bd4ca43feca33068efd84d8fd06fad3ebe7b2e0", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "2d5f799e120d0472403c1a4d268854f57de4d1ce8ff5f42cbc02f10b62b05442", - "start_line": 166, - "name": "read_backup", - "arity": 1 - }, - "write_backup/1:175": { - "line": 175, - "guard": null, - "pattern": "{:ok, path, file}", - "kind": "defp", - "end_line": 175, - "ast_sha": "5e4086636677bf1b82f9391004a8fe63362a47341f5113806ebc3fcb7569f5f4", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "5c3c7ec71d21052d7ce1c7fb21f7c787582c1cd45503268583625c48740b1bc7", - "start_line": 175, - "name": "write_backup", - "arity": 1 - }, - "sync/0:20": { - "line": 20, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 27, - "ast_sha": "a15adb8a221aabb4370126f8822a294e35aed689efafe7c2f208e7f9b0a4b2d0", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "14bfc5edb3ceed24a0ca70357cc08c53fa787b38b362c064bbd914c5c2185d6b", - "start_line": 20, - "name": "sync", - "arity": 0 - }, - "code_change/3:3": { - "line": 3, - "guard": null, - "pattern": "_old, state, _extra", - "kind": "def", - "end_line": 940, - "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "31983bfe8f79d86d314c55191170a0aaaca469968542b28c2b77e1d81dfe5530", - "start_line": 3, - "name": "code_change", - "arity": 3 - }, - "write_backup/1:176": { - "line": 176, - "guard": null, - "pattern": ":error", - "kind": "defp", - "end_line": 176, - "ast_sha": "ca2882601aaf6264708cae6d31e62c5863e9c2588a695e472b8a1a019c49e31d", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "ff0945a83def68aef03b9add8a7aecb47797229a84b72e0c5223d75413bf4644", - "start_line": 176, - "name": "write_backup", - "arity": 1 - }, - "terminate/2:3": { - "line": 3, - "guard": null, - "pattern": "_reason, _state", - "kind": "def", - "end_line": 3, - "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", - "start_line": 3, - "name": "terminate", - "arity": 2 - }, - "handle_call/3:37": { - "line": 37, - "guard": null, - "pattern": ":check_symlinks, _from, state", - "kind": "def", - "end_line": 59, - "ast_sha": "15e1c1133e3268df092df786ef3b08fc68838cd0ab75a6a55d305ea8e07821e3", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "38b6b73d7a1951437b3308a3936b5da16bce5f2e2a487f62288eaf05839e8087", - "start_line": 37, - "name": "handle_call", - "arity": 3 - }, - "can_symlink?/0:142": { - "line": 142, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 155, - "ast_sha": "f72e553f948b7c47ea89433b6596f8f43dd1122e2264e6b69817f6dfa728bf2e", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "e80929b2eaf8a186580731b98d7bf9a507dfa72921d59dcdd3f9a532a2c91533", - "start_line": 142, - "name": "can_symlink?", - "arity": 0 - }, - "run_compilers/4:399": { - "line": 399, - "guard": null, - "pattern": "[compiler | rest], args, status, diagnostics", - "kind": "defp", - "end_line": 406, - "ast_sha": "ec0fed79d2a115fdf5858e8967b26dd46128373a9bfb787379bb59c9e11fbcc9", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "451fbb47fae0c15c04355617c66f827398ea11d72420fa87ebe094c5b19b50b8", - "start_line": 399, - "name": "run_compilers", - "arity": 4 - }, - "warn_missing_mix_listener/0:187": { - "line": 187, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 189, - "ast_sha": "52d4e1bf22d7519b91225310cb8809d47a020302d2d5d69f5299f5a47bfe415b", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "8d574117dee40a21c816333b917b7fb584769f1e62aa7448facaf8ebd2ce92bf", - "start_line": 187, - "name": "warn_missing_mix_listener", - "arity": 0 - }, - "handle_cast/2:116": { - "line": 116, - "guard": null, - "pattern": "{:sync, pid, ref}, state", - "kind": "def", - "end_line": 118, - "ast_sha": "ee46c73737dd3aadb3e68f5857bef8db2ae333f87896c59222cfd173b19c1148", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "6542e194de158fa14aa613610a007de4b8c3af426fdec3278daaa4041977f1db", - "start_line": 116, - "name": "handle_cast", - "arity": 2 - }, - "mix_compile/6:210": { - "line": 210, - "guard": null, - "pattern": "{:module, Mix.Task}, compilers, apps_to_reload, compile_args, timestamp, purge_fallback?", - "kind": "defp", - "end_line": 246, - "ast_sha": "8ff574b065cbb3fca28ffc1609f9d30214f8f988f7085a053c42e9e0cea2a33c", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "9e8e48b09850eb2c2ff699002db483560ac327e1294015706faa1c5086372e34", - "start_line": 210, - "name": "mix_compile", - "arity": 6 - }, - "default_reloadable_apps/0:125": { - "line": 125, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 129, - "ast_sha": "6acc2341b95dcf4d903aab6595c80bde921b0a900c0bf74ff91613ca5b559fb7", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "ba8f90d7566a27361c49bc051fafedd0fa03f30543f97b555ddd5e5f4dc9f1be", - "start_line": 125, - "name": "default_reloadable_apps", - "arity": 0 - }, - "mix_compile_project/7:275": { - "line": 275, - "guard": null, - "pattern": "nil, _, _, _, _, _, _", - "kind": "defp", - "end_line": 275, - "ast_sha": "535bcfa8d648d52576e28667e7cc614f54068a05a33b3369c63fc783750ce1ac", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "1a7554268c5cf0d2c195f54d107ca2eb3710c2f43928bd6f52d67ebd0ba98560", - "start_line": 275, - "name": "mix_compile_project", - "arity": 7 - }, - "os_symlink/1:133": { - "line": 133, - "guard": null, - "pattern": "{:win32, _}", - "kind": "defp", - "end_line": 135, - "ast_sha": "93a93ed2d5f9eea01b205423fac2663fe82ac1e41de85350bcb8f5708071bdf0", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "b3a11dc74cb852b2e0bd0e37ac69db5292816e990d1e51d716bbb3b0fb527d83", - "start_line": 133, - "name": "os_symlink", - "arity": 1 - }, - "timestamp/0:360": { - "line": 360, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 360, - "ast_sha": "a06bc1128086e8392553788ebf17b68be4f4201c55815eb6668d59773d61becf", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "cee8e1c0678d0fb65f701112ebb0e5dc1b047b482c5ff6f5443a5a8a0157122f", - "start_line": 360, - "name": "timestamp", - "arity": 0 - }, - "with_logger_app/2:436": { - "line": 436, - "guard": null, - "pattern": "config, fun", - "kind": "defp", - "end_line": 444, - "ast_sha": "0aa47c7983543c50c03b135680542c027d53a220223a0b8792904b0f2d07466e", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "0587688d691554a7387808399b24a70c90ce04997421b34d3210d62848f8bd32", - "start_line": 436, - "name": "with_logger_app", - "arity": 2 - }, - "start_link/1:8": { - "line": 8, - "guard": null, - "pattern": "_", - "kind": "def", - "end_line": 9, - "ast_sha": "3ef624f4455e0a50950ad3edad2e84ceabb9976067d02c4c1882836abc8c1944", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "e1805dbddf7119242335e990fb2177b71999801ab3b0ff099b0c41cfb3b09312", - "start_line": 8, - "name": "start_link", - "arity": 1 - }, - "os_symlink/1:139": { - "line": 139, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 139, - "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "e0f93d19891fcf43e713b0d30e9dddfd765860ab8cf9f660de4f1b677a509e7a", - "start_line": 139, - "name": "os_symlink", - "arity": 1 - }, - "run_compiler/2:410": { - "line": 410, - "guard": null, - "pattern": "compiler, args", - "kind": "defp", - "end_line": 412, - "ast_sha": "d4b465d77e95c80195ed33f456c103b827a786dd11d338c8d38e2123313fd77e", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "ed0ec730dbe4cd6052db37bea3ae7419db0a0bcb022d547ba51e7c5e9540e02a", - "start_line": 410, - "name": "run_compiler", - "arity": 2 - }, - "load_backup/1:160": { - "line": 160, - "guard": null, - "pattern": "mod", - "kind": "defp", - "end_line": 163, - "ast_sha": "8df57cdd323ed99fea00849309fad47d5bae8f507f1aab648e10db588432479f", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "f3e5ee6278e046754994def27f3b189dfbf34b0f652f326ff30862d1acf655aa", - "start_line": 160, - "name": "load_backup", - "arity": 1 - }, - "normalize/2:415": { - "line": 415, - "guard": null, - "pattern": "result, name", - "kind": "defp", - "end_line": 428, - "ast_sha": "ac43def6fb9fbfc61c481a67aec3e1c7768b6e7b68c24d1b3784055b30ff65b3", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "0af3f3a1bb18d99b530ae7be9b4edf2e60ed0c036b130bff016440b3fb6f9880", - "start_line": 415, - "name": "normalize", - "arity": 2 - }, - "read_backup/1:173": { - "line": 173, - "guard": null, - "pattern": "_path", - "kind": "defp", - "end_line": 173, - "ast_sha": "9244a6e9b085ea0c1b33db6c78c0aac4d75e2a6adc0314a5e0b49f675c302026", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "6768602160487ac0d8d8ae010826a26f9fe5063c75973272ee04e93e4d3bdc2a", - "start_line": 173, - "name": "read_backup", - "arity": 1 - }, - "purge_modules/1:362": { - "line": 362, - "guard": null, - "pattern": "path", - "kind": "defp", - "end_line": 367, - "ast_sha": "532085bc342961909af1c78d3f9a7157d47124ae275e00c433395003fb2a18cb", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "06fd4304d24dd8fcbdac8f600f0a08161ef3ae63e300b0faa2b078b00bea9040", - "start_line": 362, - "name": "purge_modules", - "arity": 1 - }, - "mix_compile_project/7:277": { - "line": 277, - "guard": null, - "pattern": "app, apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", - "kind": "defp", - "end_line": 287, - "ast_sha": "2a70d08056430ae842bf36a05c03e96660e025e474f1d3b34c33cca44121b77c", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "5dbd281a579a2001312264b340413b6298d219b9a485dc5a45bea1ea5b8531c9", - "start_line": 277, - "name": "mix_compile_project", - "arity": 7 - }, - "mix_compile/4:320": { - "line": 320, - "guard": null, - "pattern": "compilers, compile_args, config, consolidation_path", - "kind": "defp", - "end_line": 355, - "ast_sha": "47688cbcdf52c3ca334bd36ae88111eff3f5e74486d060fd79703015aa260137", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "f73c3c98356e4402bb261bc5b6382b6e0a58d490da2fd5d29927e2476dab7345", - "start_line": 320, - "name": "mix_compile", - "arity": 4 - }, - "handle_call/3:62": { - "line": 62, - "guard": null, - "pattern": "{:reload!, endpoint, opts}, from, state", - "kind": "def", - "end_line": 113, - "ast_sha": "1ae01eaa78982fa60a9c95a786ce9086bb4d1b3891fce5638be0ec386a949eda", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "4e331f44ab17a5201f6e29a959984ff50c21964224ebdb510292ad5596ab213a", - "start_line": 62, - "name": "handle_call", - "arity": 3 - }, - "all_waiting/2:178": { - "line": 178, - "guard": null, - "pattern": "acc, endpoint", - "kind": "defp", - "end_line": 182, - "ast_sha": "ad316be342055c1328e21b638d5698056b4b702bb6be745f6f3ea6d196abc990", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "a2faab03c700827619911067b1441a5a6d8a2be2d1472f62318386e23aebee19", - "start_line": 178, - "name": "all_waiting", - "arity": 2 - }, - "check_symlinks/0:12": { - "line": 12, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 13, - "ast_sha": "4e8e2d287c098206922d307e56ce6228b702a1fb27ab57bc5df08621fca333a9", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "1029664bd0a91d06588ff83289349aaa1eac7df484d56a05a574bebc980ca1aa", - "start_line": 12, - "name": "check_symlinks", - "arity": 0 - }, - "purge_module/1:375": { - "line": 375, - "guard": null, - "pattern": "module", - "kind": "defp", - "end_line": 377, - "ast_sha": "a56a711f5834de552daa80562ee56c9b4eacede93d309d6bc9225beda8e9b7e6", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "b1d7fd3685baa44e4d541b2b3874fc347384c1efc6b53748611ca09a0b9af542", - "start_line": 375, - "name": "purge_module", - "arity": 1 - }, - "reload!/2:16": { - "line": 16, - "guard": null, - "pattern": "endpoint, opts", - "kind": "def", - "end_line": 17, - "ast_sha": "f4430b426f202a3eee7479055c2ec5ba0211b4ffc9fdfa90609bdfabb85e6c8c", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "b27e7b7bf39178feef7a2f3d9791e104405888197f3ecc1c88b9285d4fd95e34", - "start_line": 16, - "name": "reload!", - "arity": 2 - }, - "mix_compile_deps/7:259": { - "line": 259, - "guard": null, - "pattern": "deps, apps_to_reload, compile_args, compilers, timestamp, path, purge_fallback?", - "kind": "defp", - "end_line": 270, - "ast_sha": "5627b4ba528b53378a8766cbfc06edb1c924d2a1c6d3949707ed176bafb6bae8", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "2da98b17ea778f8d273ab5b3cf76e4f95ffacf4519282e5e2d33d528ae7a46d8", - "start_line": 259, - "name": "mix_compile_deps", - "arity": 7 - }, - "run_compilers/4:395": { - "line": 395, - "guard": null, - "pattern": "[], _, status, diagnostics", - "kind": "defp", - "end_line": 396, - "ast_sha": "d17b5692e701a33da0cd376674ce0f66134bed7638ffaf32e74f71908579ee07", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "116bec3dbd89e6dde80e47efbc7d8450aac0f1bf8e2540f86bd6559ab1e5923e", - "start_line": 395, - "name": "run_compilers", - "arity": 4 - }, - "mix_compile_unless_stale_config/5:291": { - "line": 291, - "guard": null, - "pattern": "compilers, compile_args, timestamp, path, purge_fallback?", - "kind": "defp", - "end_line": 314, - "ast_sha": "c4debce35d8e2db30e2b891b93f76591c8a1a8c0b18944b565aee5f04d364b9f", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "177ee325aaac3831458ec0aeaf50e48abf921fa6fca6206c446c92fd71933319", - "start_line": 291, - "name": "mix_compile_unless_stale_config", - "arity": 5 - }, - "proxy_io/1:380": { - "line": 380, - "guard": null, - "pattern": "fun", - "kind": "defp", - "end_line": 389, - "ast_sha": "6e4c61d858d55a563868514189b029fa8270cab29802302a535b75193baf2ef1", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "b4df16d2080ad61a510dd45a574eb3eef67efd719355e291c6fbe713ed1687f0", - "start_line": 380, - "name": "proxy_io", - "arity": 1 - }, - "handle_info/2:121": { - "line": 121, - "guard": null, - "pattern": "_, state", - "kind": "def", - "end_line": 122, - "ast_sha": "65ac04f4317532edd4f4e759760b6fbe89093befc57712e1d00884f951bc0c34", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "bde504cfc1bc8be6dcf1880e72de7ff231260cfd36d88c2577f8f24004e5ea9e", - "start_line": 121, - "name": "handle_info", - "arity": 2 - }, - "mix_compile/6:252": { - "line": 252, - "guard": null, - "pattern": "{:error, _reason}, _, _, _, _, _", - "kind": "defp", - "end_line": 253, - "ast_sha": "43d9095841359b34c72beda65f796f871e203371a73125d270d26d804537f1b3", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "16b70d15b2b291e84f471b27310d2e0fa65834ad6e8c589993d162d50fd71057", - "start_line": 252, - "name": "mix_compile", - "arity": 6 - }, - "init/1:33": { - "line": 33, - "guard": null, - "pattern": ":ok", - "kind": "def", - "end_line": 34, - "ast_sha": "334fa76dc0c033348e14225fe6221747e36f73ef41bb2efb980855eddfdc9b50", - "source_file": "lib/phoenix/code_reloader/server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/server.ex", - "source_sha": "ca9a986e602b40a2e6f13864bf2cf77d4f679240be55502ed5ee7f371636d312", - "start_line": 33, - "name": "init", - "arity": 1 - } - }, - "Mix.Phoenix.Scope": { - "__struct__/0:4": { - "line": 4, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 4, - "ast_sha": "333df4d514c402ff675e1ac0953e447fb385a63b5b094ac7dfec25f447dbfc52", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "f6d2eee0beb9d35dccee762f886c09483fa4253d7c4c417e6923dd6b281e220d", - "start_line": 4, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:4": { - "line": 4, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 4, - "ast_sha": "2a7f50ee20d17b75bc46ce36270ee689bec7cb840de905fdee56a52f5d934e3a", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "f6d2eee0beb9d35dccee762f886c09483fa4253d7c4c417e6923dd6b281e220d", - "start_line": 4, - "name": "__struct__", - "arity": 1 - }, - "default_scope/1:53": { - "line": 53, - "guard": null, - "pattern": "otp_app", - "kind": "def", - "end_line": 65, - "ast_sha": "646ab727e73497341bbb171de80d20bae4119b464ee1c93938060c9cc732ce05", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "0fafe5ed6ae6517da008831540cbc0b7d557f5c6a150182d6484d1f57ebf6272", - "start_line": 53, - "name": "default_scope", - "arity": 1 - }, - "new!/2:22": { - "line": 22, - "guard": null, - "pattern": "name, opts", - "kind": "def", - "end_line": 37, - "ast_sha": "9a31dd1661e10c7623f7d05d4336fa92d74426303f83c158912f8c6d15d6f7dd", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "c3f2942bdd3d3cde894f51af90e9a1ac153e2902004c0e158d22bbf36591d6f8", - "start_line": 22, - "name": "new!", - "arity": 2 - }, - "route_prefix/2:122": { - "line": 122, - "guard": "not (route_prefix == nil)", - "pattern": "scope_key, %{scope: %{route_prefix: route_prefix, route_access_path: route_access_path}} = _schema", - "kind": "def", - "end_line": 150, - "ast_sha": "2fadadf7e4e306c6d58b5f9c48094bcd60cb5b232b965a5df7574f9842978fe4", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "563bd70dff29dbc9cb9402280433e3b934033ac484eafc2647ee1bc97cdb6f64", - "start_line": 122, - "name": "route_prefix", - "arity": 2 - }, - "route_prefix/2:153": { - "line": 153, - "guard": null, - "pattern": "_scope_key, _schema", - "kind": "def", - "end_line": 153, - "ast_sha": "97d09b79b94aa2206d7a4fa04f432a57056385128e847c42ad957c9e4a12b898", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "a2ce46307479dabef96304e6e59e1602031cc87a66e836dd02bf6238eb177073", - "start_line": 153, - "name": "route_prefix", - "arity": 2 - }, - "scope_from_opts/3:75": { - "line": 75, - "guard": "is_binary(bin)", - "pattern": "_otp_app, bin, false", - "kind": "def", - "end_line": 76, - "ast_sha": "24416ce6bc694d5bbd319ff3accab74dfbc2df4f72281bd7a0f15ddc5c0b3d0a", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "7b7d37c52e8f98825bfcd9a646d42c6c2ec533d99505410de66d2c00cbedc52f", - "start_line": 75, - "name": "scope_from_opts", - "arity": 3 - }, - "scope_from_opts/3:79": { - "line": 79, - "guard": null, - "pattern": "_otp_app, _name, true", - "kind": "def", - "end_line": 79, - "ast_sha": "c8085f2fdaccbd674d288ef6a6fc851aa2f1325a92e605ec29ace625bc7d0ede", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "19368de6c24bda4d66afdc5011dc52c854b740de090f2f24551018740803c844", - "start_line": 79, - "name": "scope_from_opts", - "arity": 3 - }, - "scope_from_opts/3:81": { - "line": 81, - "guard": null, - "pattern": "otp_app, nil, _", - "kind": "def", - "end_line": 81, - "ast_sha": "01563c97b0661419a5ff6ba401774128a0467adc4e8c3b76d5b3445ea5bb6056", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "fcb5aaa77eade1d253caa3740e89e22897d05989329fa05a2ad1962f24f8d439", - "start_line": 81, - "name": "scope_from_opts", - "arity": 3 - }, - "scope_from_opts/3:83": { - "line": 83, - "guard": null, - "pattern": "otp_app, name, _", - "kind": "def", - "end_line": 94, - "ast_sha": "518fbddaf3b064fff6c7f3dc32afb354f442fac5146ee631e8d7ac91c3b0675c", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "b0bae185aebea0a3d871b6000c28df7dce260fee1cc4be7f0f9c0ffcaab2539e", - "start_line": 83, - "name": "scope_from_opts", - "arity": 3 - }, - "scopes_from_config/1:44": { - "line": 44, - "guard": null, - "pattern": "otp_app", - "kind": "def", - "end_line": 47, - "ast_sha": "53a5dcde9c4ae33ff713e49d8dd9cdd55e2127776df28371e6bb565d56834509", - "source_file": "lib/mix/phoenix/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/scope.ex", - "source_sha": "64ef553c825764806b72942bfdac81aa94db29855bb88dac2f2da80d678e3788", - "start_line": 44, - "name": "scopes_from_config", - "arity": 1 - } - }, - "Phoenix.Param.Atom": { - "__impl__/1:78": { - "line": 78, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 78, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "de2003188243d5858057dba638c8139359d7f6807b59fe1b6f10a42a9cd1c0da", - "start_line": 78, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:79": { - "line": 79, - "guard": null, - "pattern": "nil", - "kind": "def", - "end_line": 80, - "ast_sha": "656c1525e53d3fe0bab71fc5c6c5a81f28870417c4dd45d9938bbf2e33ec591e", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "5adea25f1d81bedb826dee0bbb543588d07138fe9e530b14d2985db17277c8c4", - "start_line": 79, - "name": "to_param", - "arity": 1 - }, - "to_param/1:83": { - "line": 83, - "guard": null, - "pattern": "atom", - "kind": "def", - "end_line": 84, - "ast_sha": "45903349c732f172e12d423567d29750e0a94b3349a9f224604d38ac862f087e", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "aa7b4b710ab4655cb4c4c042f0c2cbcdef47dc4a74b0f52ff2e5169513b44b02", - "start_line": 83, - "name": "to_param", - "arity": 1 - } - }, - "Phoenix.Param.Map": { - "__impl__/1:88": { - "line": 88, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 88, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "24ec10101eec006b1ad959e9447d89705819d5207d89b4b708eec4aaa5cb42cd", - "start_line": 88, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:89": { - "line": 89, - "guard": null, - "pattern": "map", - "kind": "def", - "end_line": 91, - "ast_sha": "626fcf7967578b8a0da4214fa93950a286decbf9e9726becd709b52ad540fe5f", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "f0601ac2aee88f1b14135f9c0190f2e5ede449cd3a75808d93e163a10dbb48f8", - "start_line": 89, - "name": "to_param", - "arity": 1 - } - }, - "Phoenix.Transports.LongPoll.Server": { - "broadcast_from!/3:129": { - "line": 129, - "guard": "is_binary(client_ref)", - "pattern": "state, client_ref, msg", - "kind": "defp", - "end_line": 130, - "ast_sha": "0882e4f8e008faa7703b4033e499221859a9c90bb7afb3b47efb0201d1a8c1fc", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "5f9f48f3d63887f9f550817a361c8f87c91cae943a22fde345425d670379b45f", - "start_line": 129, - "name": "broadcast_from!", - "arity": 3 - }, - "broadcast_from!/3:132": { - "line": 132, - "guard": "is_pid(client_ref)", - "pattern": "_state, client_ref, msg", - "kind": "defp", - "end_line": 133, - "ast_sha": "df20d134ad38825b9d2cf5e22162c1eae4bcb9863e09a2efcedb43f063f652fc", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "0eabf57bdc893f937fdd5da617a9a4ec6d1293d6e2a5e7dabaaf1d2515f784a3", - "start_line": 132, - "name": "broadcast_from!", - "arity": 3 - }, - "child_spec/1:4": { - "line": 4, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 862, - "ast_sha": "b6e9e21767cef3cb2d495e5bba3998954e1b8e716f0c12b30db6cb1fb7440fd0", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", - "start_line": 4, - "name": "child_spec", - "arity": 1 - }, - "code_change/3:4": { - "line": 4, - "guard": null, - "pattern": "_old, state, _extra", - "kind": "def", - "end_line": 940, - "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", - "start_line": 4, - "name": "code_change", - "arity": 3 - }, - "handle_call/3:4": { - "line": 4, - "guard": null, - "pattern": "msg, _from, state", - "kind": "def", - "end_line": 884, - "ast_sha": "d154285ffa31c40a154abcc529ee5f8e6b815c60b9c4c00bbba52fd368dd5b68", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", - "start_line": 4, - "name": "handle_call", - "arity": 3 - }, - "handle_cast/2:4": { - "line": 4, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 929, - "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "6d70e265ed88adee55f02e9074c6bffdf7dbde04fa5686430b1f91ae55590ff1", - "start_line": 4, - "name": "handle_cast", - "arity": 2 - }, - "handle_info/2:105": { - "line": 105, - "guard": null, - "pattern": "message, state", - "kind": "def", - "end_line": 119, - "ast_sha": "9dffc606af15ac1825a571031be42d523e2651b2c85da452343f4a392a95f8af", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "204655877c295719af91c735a37f208c64872caa3be2daef60249eaa94629e22", - "start_line": 105, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:48": { - "line": 48, - "guard": null, - "pattern": "{:dispatch, client_ref, {body, opcode}, ref}, state", - "kind": "def", - "end_line": 66, - "ast_sha": "f42a34a399decb4203335d9b331b29584b8299c0c49a6e19187ec7d4e23b3666", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "940b2f1aff462608fbf331ef64baaa327d2cd8b76e280399afc51aa2b6d941eb", - "start_line": 48, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:70": { - "line": 70, - "guard": null, - "pattern": "{:subscribe, client_ref, ref}, state", - "kind": "def", - "end_line": 72, - "ast_sha": "df1e159f6895355bfcafbd66917ff9eeff7267d22eacca7d1e23653044d20815", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "06d27e2baed086aca33eaa5d86e81fb4ec94f386a51d5286c5bacea416f26426", - "start_line": 70, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:75": { - "line": 75, - "guard": null, - "pattern": "{:flush, client_ref, ref}, state", - "kind": "def", - "end_line": 82, - "ast_sha": "35dfde4d29f0010151e10ba5ac871455c9e034487ceeaabfc5624aa9b0f1159a", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "2f61446933f8972ee45cdf3643081d8582b529ca0742ad8324f102b67e914c70", - "start_line": 75, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:86": { - "line": 86, - "guard": null, - "pattern": "{:expired, client_ref, ref}, state", - "kind": "def", - "end_line": 92, - "ast_sha": "ffefce60ebe41d4780083b7ab77f27970639a996cf5fb0d28c73b333b0d669de", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "ca1c1bcdb7f363cda958fd2ca20b6c9c64330c75f7dd0226c53087a8e59d4d29", - "start_line": 86, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:96": { - "line": 96, - "guard": null, - "pattern": ":shutdown_if_inactive, state", - "kind": "def", - "end_line": 101, - "ast_sha": "74f2bf736ae59b584ac93898578e12f27075552c1878f9b95b5e61e5f7d421ad", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "1d95cf1253efd99dc4c07815bf2297fee184b78662f5018c2525621f8b91d382", - "start_line": 96, - "name": "handle_info", - "arity": 2 - }, - "init/1:11": { - "line": 11, - "guard": null, - "pattern": "{endpoint, handler, options, params, priv_topic, connect_info}", - "kind": "def", - "end_line": 43, - "ast_sha": "cd9f8e100072620bd66065c1c3e55c6bf9d0930d41923dc5ade0f4bfa55d7790", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "e20c52ef73c3cf535acf6567cfaeba22228ea9408746fca862820211863b1a0b", - "start_line": 11, - "name": "init", - "arity": 1 - }, - "notify_client_now_available/1:149": { - "line": 149, - "guard": null, - "pattern": "state", - "kind": "defp", - "end_line": 152, - "ast_sha": "b178042e7357a0e5345c0fa766f7862961eb4b913d04e43e8e2902c9d0ab3bfe", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "e3496845b0b71a2c31b70e426666b4602a9aafe2674f2252192d8b2773ab08bf", - "start_line": 149, - "name": "notify_client_now_available", - "arity": 1 - }, - "now_ms/0:156": { - "line": 156, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 156, - "ast_sha": "c2e635558108b34d89887a7285e4a2a6c0ec0e5f69bab3d82a5d1d972542afb8", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "2168725c05e76dc59d568394ecaae806ffb3d84d4ee471c8675d1e443a63ec75", - "start_line": 156, - "name": "now_ms", - "arity": 0 - }, - "publish_reply/2:135": { - "line": 135, - "guard": "is_map(reply)", - "pattern": "state, reply", - "kind": "defp", - "end_line": 141, - "ast_sha": "64c1daf5640ea08f11211e2a686230468f8557499fcc638d4deed94b0742a4fd", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "cd249f6fe48f1199e6e7e6c515914b08041d80d041f088ee04b916df05269057", - "start_line": 135, - "name": "publish_reply", - "arity": 2 - }, - "publish_reply/2:144": { - "line": 144, - "guard": null, - "pattern": "state, reply", - "kind": "defp", - "end_line": 146, - "ast_sha": "3481cca10b5ed90f47f0360b333286c522a8a845e9f448288678019d0f0d34fa", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "2d32779f635a850f948a7eefb986f958d42da77ed9dd64e4d3226d1ce367416c", - "start_line": 144, - "name": "publish_reply", - "arity": 2 - }, - "schedule_inactive_shutdown/1:158": { - "line": 158, - "guard": null, - "pattern": "window_ms", - "kind": "defp", - "end_line": 159, - "ast_sha": "2c138af0c4b88ea154149917e13200e939bbc98be2e328b49085a45477df925c", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "1813f6d3e71eeb4f36036a86e0af2475e6a7c438616cde3788843cd93c7820e1", - "start_line": 158, - "name": "schedule_inactive_shutdown", - "arity": 1 - }, - "start_link/1:7": { - "line": 7, - "guard": null, - "pattern": "arg", - "kind": "def", - "end_line": 8, - "ast_sha": "5f13b4d4cf59c3791ecf0e6896b77bdd86dd1c2c62ff88515286fb0087180570", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "0aeb13552dc5379a6d33464ab9c4b0de64d1b892deb0c1d7726f66bb188fa46b", - "start_line": 7, - "name": "start_link", - "arity": 1 - }, - "terminate/2:123": { - "line": 123, - "guard": null, - "pattern": "reason, state", - "kind": "def", - "end_line": 125, - "ast_sha": "33b582c17fb56303f28e80811e59555d2b4a4e9666a3640c9d1c3f3cc2651db4", - "source_file": "lib/phoenix/transports/long_poll_server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll_server.ex", - "source_sha": "92d07954ae2170431cc34ae80a716b34df5fa2108697845d9dbcbbc5921cda65", - "start_line": 123, - "name": "terminate", - "arity": 2 - } - }, - "Plug.Exception.Phoenix.ActionClauseError": { - "__impl__/1:69": { - "line": 69, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 69, - "ast_sha": "e3f2237efa36a7849b77d5da300b6de95b75f921b007de05bbe1549428db123b", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "7673a338de29039113f06428539301e66d2653703194481aa09987af68928136", - "start_line": 69, - "name": "__impl__", - "arity": 1 - }, - "actions/1:71": { - "line": 71, - "guard": null, - "pattern": "_", - "kind": "def", - "end_line": 71, - "ast_sha": "cd9a1ecf3037be6bf542dbbbf970b1538abea2533a8a8759803a3870342601ce", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "44ae2878a59fd5377a2ccec6625b3f6663fa63d92176bce3fb83efc3cd73e2e5", - "start_line": 71, - "name": "actions", - "arity": 1 - }, - "status/1:70": { - "line": 70, - "guard": null, - "pattern": "_", - "kind": "def", - "end_line": 70, - "ast_sha": "037fd48b4767ef7491dd1f8eea9af6ffb37c79fcbc09465d86cfd2c7d6f8bd68", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "4e5608efe32e7cac74db1f8684121648721d7f67f846bf825a86b4bf67652fc9", - "start_line": 70, - "name": "status", - "arity": 1 - } - }, - "Phoenix.NotAcceptableError": { - "__struct__/0:15": { - "line": 15, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 15, - "ast_sha": "56bb5050646cb7904fa46d58afa7900cc0d449380e4083108d111b5be2e59f66", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", - "start_line": 15, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:15": { - "line": 15, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 15, - "ast_sha": "d49d6929d799d6a3c55c7cd83949e797cab094762d0109a9d7f600e14f003d24", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", - "start_line": 15, - "name": "__struct__", - "arity": 1 - }, - "exception/1:15": { - "line": 15, - "guard": "is_list(args)", - "pattern": "args", - "kind": "def", - "end_line": 15, - "ast_sha": "ac1551bd7821466ef6422bbcddd9b63f298fec85dec90490f13cd4e3dcd9a53c", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", - "start_line": 15, - "name": "exception", - "arity": 1 - }, - "message/1:15": { - "line": 15, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 15, - "ast_sha": "1a55e71ad2c4b00984c0ea1502576b3d74d57d2930b0f0a587f122efb16738d3", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "f57b463e77120e32b6a7e795a203280b7a8c6f4cd121137f926267f17e530f9e", - "start_line": 15, - "name": "message", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Release": { - "docker_instructions/0:208": { - "line": 208, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 208, - "ast_sha": "c7adad6daad081cf770d778db8ab85ebb7885a4b316e9eb28367d3ec5dd62a41", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "5eae4f8dbe814a29dcaf194a7dba8e433caa2b8ee05271f7b7e71b8ea5f55f94", - "start_line": 208, - "name": "docker_instructions", - "arity": 0 - }, - "ecto_instructions/1:200": { - "line": 200, - "guard": null, - "pattern": "app", - "kind": "defp", - "end_line": 204, - "ast_sha": "bb29a9b7c31040c4329311ed7f10c3ad0737faee14c7c331cb347a7674e730cc", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "70814f7b86161c2bb4132a904822d246903a4dffbcf32711426bc2d8fa942604", - "start_line": 200, - "name": "ecto_instructions", - "arity": 1 - }, - "ecto_sql_installed?/0:233": { - "line": 233, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 233, - "ast_sha": "4dfbee2c44c4737eb26c7b1b290f4d85be94a6f019eeeac28756e2f25a60619a", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "44572bde50a3c8d990c5ea6c3c89efd5bca9fa86424cf071f3bd4d597943b756", - "start_line": 233, - "name": "ecto_sql_installed?", - "arity": 0 - }, - "elixir_and_debian_vsn/2:242": { - "line": 242, - "guard": null, - "pattern": "elixir_vsn, otp_vsn", - "kind": "defp", - "end_line": 253, - "ast_sha": "30108abdbe6acca181f8f2e08a60749dab2dd1e3a6ff572afb65de272ad66bd6", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "4864f5ec66929d8197142fddbaa4f32aeb990fa6ecf8200855fa79fcf5515253", - "start_line": 242, - "name": "elixir_and_debian_vsn", - "arity": 2 - }, - "ensure_app!/1:311": { - "line": 311, - "guard": null, - "pattern": "app", - "kind": "defp", - "end_line": 315, - "ast_sha": "9e5d17f833c592fa94823585e6c3caee2e9ccec25044b01f15c59d016e5975cd", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "5432eaa5684589bc4716e4e07a8661a0a1dd8c2934955746c1cd6893797e1c82", - "start_line": 311, - "name": "ensure_app!", - "arity": 1 - }, - "fetch_body!/1:319": { - "line": 319, - "guard": null, - "pattern": "url", - "kind": "defp", - "end_line": 358, - "ast_sha": "84454d18ae3ac7fc64386fc92cc8271ed7f7ed823f36f9b4e6f77fa61f59ad76", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "c219b97a54b752548a687f2ca5ef0b581540af6e26ff8d301d8e36e043501bb3", - "start_line": 319, - "name": "fetch_body!", - "arity": 1 - }, - "gen_docker/2:258": { - "line": 258, - "guard": null, - "pattern": "binding, opts", - "kind": "defp", - "end_line": 305, - "ast_sha": "e8fae4feccbf65e1830836c8e905da03edde3c4ee8f06f34902fe8e9a1470d63", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "51e3b5d9166e48209b8182561277821e74077cd9fb3c2279659276713f5cda92", - "start_line": 258, - "name": "gen_docker", - "arity": 2 - }, - "otp_vsn/0:366": { - "line": 366, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 376, - "ast_sha": "dd5a9d13ffe250793fa704be46aa247d3303928d0808c9dd35d073544814bb79", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "24e0327c673d1d68405566438478551e1619237621ac24c748d486ddf4f26eda", - "start_line": 366, - "name": "otp_vsn", - "arity": 0 - }, - "parse_args/1:186": { - "line": 186, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 197, - "ast_sha": "7c0c0ece3bbb3ec2c452a3a468f143f46a0551cbd6b13455028937b7d1b23cb5", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "9a4997ba5d91aa6f70cba3e4005fd106ac30e5e67d267e7b408044405860fb16", - "start_line": 186, - "name": "parse_args", - "arity": 1 - }, - "paths/0:219": { - "line": 219, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 219, - "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", - "start_line": 219, - "name": "paths", - "arity": 0 - }, - "post_install_instructions/3:223": { - "line": 223, - "guard": null, - "pattern": "path, matching, msg", - "kind": "defp", - "end_line": 229, - "ast_sha": "5a7e484f60b79598ff73e3a185e03d5c0f103ce01e8b5a41cad633bbdf92a6f3", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "64ecd96b406a989aa8155452b53f5094f235cc36720333d76571a6c8e4efcbb1", - "start_line": 223, - "name": "post_install_instructions", - "arity": 3 - }, - "protocol_versions/0:361": { - "line": 361, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 363, - "ast_sha": "cb1de9690d1b5e421a1bbec56f94b8d7f60b875bae57bbe2404b64f3b58ec822", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "4979acdeec3f4047b7f19e03be42ad07c1fbf8961abbc3bde3c126bd73946755", - "start_line": 361, - "name": "protocol_versions", - "arity": 0 - }, - "run/1:80": { - "line": 80, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 180, - "ast_sha": "807678791f0f45cff7cf9382ba817cf11426f877ab41285e001ae7035a086e6a", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "c72418fc9b28e06d8b52607bc7ee3059a3572d8946925b200a6560aec101e22d", - "start_line": 80, - "name": "run", - "arity": 1 - }, - "socket_db_adaptor_installed?/0:235": { - "line": 235, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 238, - "ast_sha": "8c6c7d9664d94c5696f5759b76736e1969219d036eb9f381fca6eb33a753975d", - "source_file": "lib/mix/tasks/phx.gen.release.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.release.ex", - "source_sha": "d14bfa11378e250a2def3c9aa39f0a47d8052fc6ed7c2ffcbfe48eb491a20bcd", - "start_line": 235, - "name": "socket_db_adaptor_installed?", - "arity": 0 - } - }, - "Phoenix.Endpoint.SyncCodeReloadPlug": { - "call/2:18": { - "line": 18, - "guard": null, - "pattern": "conn, {endpoint, opts}", - "kind": "def", - "end_line": 18, - "ast_sha": "05a97e9e1a3731f6a11357fb67d37983d878b549d8e015712cf9a2736588c26e", - "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_sha": "c2a739704df8abfb9ec35f5cc3bf36d859254bbee6757913662b1f5f3155d397", - "start_line": 18, - "name": "call", - "arity": 2 - }, - "do_call/4:20": { - "line": 20, - "guard": null, - "pattern": "conn, endpoint, opts, retry?", - "kind": "defp", - "end_line": 32, - "ast_sha": "b14c198edd6e82d7450061ed3a857548f43f82f71ce62c99c3bfdba42d3ff00e", - "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_sha": "1e5d31bb135f070afdb1301036e311fe9762890aac48c2662a3a8e0e4f52e1eb", - "start_line": 20, - "name": "do_call", - "arity": 4 - }, - "init/1:16": { - "line": 16, - "guard": null, - "pattern": "{endpoint, opts}", - "kind": "def", - "end_line": 16, - "ast_sha": "20f1b5f461a9328fc607904ed80575196927b4bee39127c71f6c3b232d08a1d1", - "source_file": "lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/sync_code_reload_plug.ex", - "source_sha": "d3c3e24e0fbc098e3062a50c4a605c48ed39619db6811460c364875c60fb2d38", - "start_line": 16, - "name": "init", - "arity": 1 - } - }, - "Phoenix.Param.Any": { - "__deriving__/3:96": { - "line": 96, - "guard": null, - "pattern": "module, struct, options", - "kind": "defmacro", - "end_line": 116, - "ast_sha": "aca6de9f6e69c2e3cc61322390661f34e1a64d4995a732388a170bc8c4b8617d", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "afce5f22d361ce7ed72176cafe08e3c34defb6dcfa7680774bc36fb3e78af22f", - "start_line": 96, - "name": "__deriving__", - "arity": 3 - }, - "__impl__/1:95": { - "line": 95, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 95, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "9a820ad472710dbdd14b89e270413abac90449492fd49338a15b308053c6170c", - "start_line": 95, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:121": { - "line": 121, - "guard": null, - "pattern": "%{id: nil}", - "kind": "def", - "end_line": 122, - "ast_sha": "d0e5c57a7cbecdeb0bd816c35f78345495c34c37beda3e1b96c6c977621cf9a1", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "79c97f1f98dbf12a37d02e8d72aba4a1f485fec22fcffbc2b5bf2bd281ffbcf9", - "start_line": 121, - "name": "to_param", - "arity": 1 - }, - "to_param/1:125": { - "line": 125, - "guard": "is_integer(id)", - "pattern": "%{id: id}", - "kind": "def", - "end_line": 125, - "ast_sha": "8ca6b204a35a6fbd5ae33bb2b7bf5107843239636985740c50cd023c9d0abd22", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "686bd5c91229667b3b4262a0faf36a33d57f4341209df4007be21fd65f7354a8", - "start_line": 125, - "name": "to_param", - "arity": 1 - }, - "to_param/1:126": { - "line": 126, - "guard": "is_binary(id)", - "pattern": "%{id: id}", - "kind": "def", - "end_line": 126, - "ast_sha": "297ef37fd78aa6b75a586dc942ea0b61edbb943ab0e4dcdd8476591b9f9c5f91", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "faea66b7b0170e6a4ba8f2f2c166ed95587c7061216c4a2574e6ceb4a473c23f", - "start_line": 126, - "name": "to_param", - "arity": 1 - }, - "to_param/1:127": { - "line": 127, - "guard": null, - "pattern": "%{id: id}", - "kind": "def", - "end_line": 127, - "ast_sha": "fabf2e9a9120ae922fa2f5c4b57f61f3bc13e334e72d0abef75c6f59c525e4ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "c9fdeae5374fe91de33a7c1ccee8eeba55bc3f30b66c5aa78985d83fb60d0c77", - "start_line": 127, - "name": "to_param", - "arity": 1 - }, - "to_param/1:129": { - "line": 129, - "guard": "is_map(map)", - "pattern": "map", - "kind": "def", - "end_line": 133, - "ast_sha": "45c5ac2176a244263a0fd08150596eba96f92e7a8297d504d11e2477d2133571", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "e7d8461d237b4ada5abcc8b3c51dc2bf935993d2b799750e12c336a4df8ae7ec", - "start_line": 129, - "name": "to_param", - "arity": 1 - }, - "to_param/1:136": { - "line": 136, - "guard": null, - "pattern": "data", - "kind": "def", - "end_line": 137, - "ast_sha": "ceff7b724151d9bbe2eef567fb7baba53aa210272ce782b4f261032fff1c955d", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "03686fdddfebef033425200c9fc3cc266a00e0a61a8df81bb0c4703ba7bc35d1", - "start_line": 136, - "name": "to_param", - "arity": 1 - } - }, - "Phoenix.Socket.Reply": { - "__struct__/0:68": { - "line": 68, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 68, - "ast_sha": "acd35a2ebf5a8237fc33ea6bdec216e8f65bed2968f9172a6556430067da01f1", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "9e833359d6ac4f243e0f7935cdfda47309ef8ec9924378bd7a3f134924277290", - "start_line": 68, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:68": { - "line": 68, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 68, - "ast_sha": "50f6979e1713136ecd3a45bb43a0193973b22b1a8f25acd4156d4b3491834b3d", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "9e833359d6ac4f243e0f7935cdfda47309ef8ec9924378bd7a3f134924277290", - "start_line": 68, - "name": "__struct__", - "arity": 1 - } - }, - "Phoenix.ChannelTest": { - "fetch_test_supervisor!/1:276": { - "line": 276, - "guard": null, - "pattern": "options", - "kind": "defp", - "end_line": 288, - "ast_sha": "e830dec93b6a349234da11351daa93dfcedb0d90b11e0b072fea04b2411ca6cf", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "b0e8f163acd3c5fea1ba65ef6e86b2bede7030516fa34716ea710ea18f374487", - "start_line": 276, - "name": "fetch_test_supervisor!", - "arity": 1 - }, - "join/3:416": { - "line": 416, - "guard": "is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, topic, payload", - "kind": "def", - "end_line": 417, - "ast_sha": "c98d02e949016cf8e82e96ab1aced9de1612913a60de29ef3f0d8eeb519f9d36", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "7dcc836f31251e3f7564cbc2ac81cfc32c512a1e4d54ae5e924f6423fc84b3d7", - "start_line": 416, - "name": "join", - "arity": 3 - }, - "socket/4:235": { - "line": 235, - "guard": null, - "pattern": "socket_module, socket_id, socket_assigns, options", - "kind": "defmacro", - "end_line": 236, - "ast_sha": "c256c5b3b0d3febba238bdeb621493059cc6e7c20a1f11f0ceb43f1f727c3f3d", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "106db6eb1120d4f7182c70668e55b3cc708867970b689affa608ce9503b3e031", - "start_line": 235, - "name": "socket", - "arity": 4 - }, - "refute_broadcast/2:672": { - "line": 672, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 672, - "ast_sha": "aeb8f96f269e883eafe5786bc6ddbf96bfc80664a7d8c05108f4834116fe181d", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "cc3103c76bd35e7caac76d25b4418f7402546903981410002133ab4aba17d17a", - "start_line": 672, - "name": "refute_broadcast", - "arity": 2 - }, - "refute_broadcast/3:672": { - "line": 672, - "guard": null, - "pattern": "event, payload, timeout", - "kind": "defmacro", - "end_line": 675, - "ast_sha": "a8bd35df6c4bcfb2cebf9138ce6192fefddacfeb165c41934752dcb93afa3817", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "f081eb83b702afaf26611476255264f38cc08e4344f32ef9cbe80017e5f00455", - "start_line": 672, - "name": "refute_broadcast", - "arity": 3 - }, - "__stringify__/1:701": { - "line": 701, - "guard": null, - "pattern": "%{} = params", - "kind": "def", - "end_line": 702, - "ast_sha": "255a5ae107dfb0562a6d0bd4ac29b0d341e0b0b54bae04b88391dc3edf0a7b02", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "a83a7abf3230b564d372b2ffebfcbc6040a21c2a504742cb4f6b9b0c8e57b379", - "start_line": 701, - "name": "__stringify__", - "arity": 1 - }, - "broadcast_from!/3:525": { - "line": 525, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket, event, message", - "kind": "def", - "end_line": 527, - "ast_sha": "ed61a4400524b57cab8badea21c025a531524b58c86384ad29f5530fadd732e8", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "27426976b9ce706b5a685f1c216e434d453320671ed0d82852090862ee3006ec", - "start_line": 525, - "name": "broadcast_from!", - "arity": 3 - }, - "subscribe_and_join!/3:357": { - "line": 357, - "guard": "is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, topic, payload", - "kind": "def", - "end_line": 359, - "ast_sha": "be6ed4510adedcc85ecb318a3663545662275de56ff9dcf93f53a708e9f34f5d", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "fe6c134bf0ec7022744c3237efe2763ce0868e2fe4889d8d3ae50f96ad4f6f44", - "start_line": 357, - "name": "subscribe_and_join!", - "arity": 3 - }, - "socket/1:208": { - "line": 208, - "guard": null, - "pattern": "socket_module", - "kind": "defmacro", - "end_line": 209, - "ast_sha": "ca842178fe8458f81072c09e67c4cd5ff042aaa258f3260428c7f1d7960b7e50", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "a18bdd8b2b7405d2cd5c3c00a1914ac13fc2cfcdd6fc113f89cdcbd95348b040", - "start_line": 208, - "name": "socket", - "arity": 1 - }, - "assert_broadcast/2:654": { - "line": 654, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 654, - "ast_sha": "8bf20c36a7f177cf0972ff47dd6a794dd8fdba0428a913135b13be3d3eb4373a", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "c1ae207c46507efdf86035a01b6d27c626f26eb510828ab6a752b2463877089c", - "start_line": 654, - "name": "assert_broadcast", - "arity": 2 - }, - "first_socket!/1:269": { - "line": 269, - "guard": null, - "pattern": "endpoint", - "kind": "defp", - "end_line": 272, - "ast_sha": "656d8e32b7e2fb127afccb6a05d81fd00cf71506e8fb7e8bd84e5df9df8db612", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "4dcc7c9b7911955bd55b07c43aa8ff4870830eac92f6796c0b1bdeaa8ca79efb", - "start_line": 269, - "name": "first_socket!", - "arity": 1 - }, - "join/4:428": { - "line": 428, - "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", - "kind": "def", - "end_line": 456, - "ast_sha": "6ed35babba52ba91b954a05a696371a1df29a4dd4637a28d7168adadd3da0fc4", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "b62718e08538baf1c82094448156942d5f462bcd9b76c2f8c6975e14aa181172", - "start_line": 428, - "name": "join", - "arity": 4 - }, - "match_topic_to_channel!/2:679": { - "line": 679, - "guard": null, - "pattern": "socket, topic", - "kind": "defp", - "end_line": 694, - "ast_sha": "786e30035901ac33e91a1cdd0ed2da734e477bdfb4983846e95780f240b74083", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "361133c3e3037413f68dbce69c7410303cb43b77da3b5ead92ac9e71c650a55f", - "start_line": 679, - "name": "match_topic_to_channel!", - "arity": 2 - }, - "__connect__/4:326": { - "line": 326, - "guard": null, - "pattern": "endpoint, handler, params, options", - "kind": "def", - "end_line": 348, - "ast_sha": "41ee570a08b58f96655426ed37c4bcee62598ee886ba010c67f800dc47f4981a", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "e9b5f1eb244262420c425b9e22e51952e0baca3adfc0ad3869257646965d4ec6", - "start_line": 326, - "name": "__connect__", - "arity": 4 - }, - "refute_reply/3:626": { - "line": 626, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 626, - "ast_sha": "021c0f97980f9d1dd869a2f57a60d10b20bca8dd836c99c6555430cdebdb5627", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "8fae7916f4434663b7704146aa3f6597f56a5ea37bd1da5b4d5b74a0f8c80992", - "start_line": 626, - "name": "refute_reply", - "arity": 3 - }, - "refute_reply/2:626": { - "line": 626, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 626, - "ast_sha": "2a66b3223461c7339e6cedc6ea4112ddd3278cff5e0ae6d2b6cd022855f0f7f0", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "8fae7916f4434663b7704146aa3f6597f56a5ea37bd1da5b4d5b74a0f8c80992", - "start_line": 626, - "name": "refute_reply", - "arity": 2 - }, - "refute_push/2:581": { - "line": 581, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 581, - "ast_sha": "d8abf3b8fec8769c848f9e58d5ae66ff6643c2ad32ab4b465320059e4150f958", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "8b8ce3c9b00667451718a39b6deb73a1998bc505ea7013e5f64ee449f8de8f89", - "start_line": 581, - "name": "refute_push", - "arity": 2 - }, - "subscribe_and_join!/3:369": { - "line": 369, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 369, - "ast_sha": "a57c7cf3133b778fe65fa6f11c1e4ce383143ddb8470f922b764d7be31068ab3", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "2441eee163534ec1de73456914c357a39fda794d23f7678fd9c6e544d50e3f11", - "start_line": 369, - "name": "subscribe_and_join!", - "arity": 3 - }, - "close/1:501": { - "line": 501, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 501, - "ast_sha": "5479b2099f89986600871c22e5ae7f7634369508d542032f3c5a1f36e69e6307", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "4fa337a7b80641b04850ea79f4e238c6dda12f866e24787c671d4bc575b06e84", - "start_line": 501, - "name": "close", - "arity": 1 - }, - "assert_reply/2:604": { - "line": 604, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 604, - "ast_sha": "efc4bdbfc72e33dca0a7f596d2152d480975a10c04d0f6cfd7c9f46075c69b83", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "0a69a7ddd645f22c15e83bc209eff765a2f88e12be1373098140fb09b7d81d8d", - "start_line": 604, - "name": "assert_reply", - "arity": 2 - }, - "close/2:501": { - "line": 501, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket, timeout", - "kind": "def", - "end_line": 502, - "ast_sha": "b328b4e378ee6223b318f2672e714c9c86719df925af7efb2fb69e84a2b850ec", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "9cd3c8139b05f1e4f817eb377516c9b260b0050bdedeb0f048792677b940cda5", - "start_line": 501, - "name": "close", - "arity": 2 - }, - "refute_push/3:581": { - "line": 581, - "guard": null, - "pattern": "event, payload, timeout", - "kind": "defmacro", - "end_line": 585, - "ast_sha": "db913e5ad782d5f0069e39b0915112bb325e541f3b653e8bdc915626f876c59b", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "f7cced920138e97929810d9c152bfa83716708f72963b35f95c82fe3720fe10c", - "start_line": 581, - "name": "refute_push", - "arity": 3 - }, - "assert_broadcast/3:654": { - "line": 654, - "guard": null, - "pattern": "event, payload, timeout", - "kind": "defmacro", - "end_line": 657, - "ast_sha": "2cc76a3a0182b89e3c9e5a667d0e54036e425b84f942700d6b24cb9c7c6ab427", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "456b7e223c81be0fa2ab18c2e91440db1ae957919be61f07529ba4fb2c0283c1", - "start_line": 654, - "name": "assert_broadcast", - "arity": 3 - }, - "assert_reply/4:604": { - "line": 604, - "guard": null, - "pattern": "ref, status, payload, timeout", - "kind": "defmacro", - "end_line": 610, - "ast_sha": "054ed7bdd53c1f8d658dc1457b8133289f360d4bd1424169e3941deab575b634", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "17654721110d2af5fc805af4c8e247c1f0ae9af37ab4797b2cb3ffaff82548f3", - "start_line": 604, - "name": "assert_reply", - "arity": 4 - }, - "connect/3:310": { - "line": 310, - "guard": null, - "pattern": "handler, params, options", - "kind": "defmacro", - "end_line": 321, - "ast_sha": "3a614dc1474b0a1407b1a4c45ccd96ad9241cf3aafb1dcd6668576c304f66526", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "6afe5c7a4c52a8dfdff645de8c7d2bedb7fa408d0c27dce638c3d4cb7582ec9b", - "start_line": 310, - "name": "connect", - "arity": 3 - }, - "join/3:428": { - "line": 428, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 428, - "ast_sha": "5bc059f1b9da3d6679956425ce8421497106102ebe1833368e581bb832453ac4", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "8b471f4859782316821375563635b970de121ced32729923a2baf3be93fd741c", - "start_line": 428, - "name": "join", - "arity": 3 - }, - "assert_reply/3:604": { - "line": 604, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 604, - "ast_sha": "cbad7e2c54e6ec201b75757ea9658723f3a8958170336c2e2db3eea2a7d61a5a", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "0a69a7ddd645f22c15e83bc209eff765a2f88e12be1373098140fb09b7d81d8d", - "start_line": 604, - "name": "assert_reply", - "arity": 3 - }, - "subscribe_and_join/3:404": { - "line": 404, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 404, - "ast_sha": "ffa28165f4c49bd92f5bba3710d31fda952082b788970540c7a8be9ac7c0ce0a", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "f15248e0fb996dae59e0ee06f1d52b5df96cd40ff1b0167cceaab70a24e2d0b3", - "start_line": 404, - "name": "subscribe_and_join", - "arity": 3 - }, - "__stringify__/1:699": { - "line": 699, - "guard": null, - "pattern": "%{__struct__: _} = struct", - "kind": "def", - "end_line": 700, - "ast_sha": "4b9761dbfc3bcd123717a1b7e01f1a20c5e724b682ee30613f1f50acd314c759", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "9387c493c07938300ad7514a9335640fc197981e85d6abf2612fef9ce88bf291", - "start_line": 699, - "name": "__stringify__", - "arity": 1 - }, - "__stringify__/1:703": { - "line": 703, - "guard": "is_list(params)", - "pattern": "params", - "kind": "def", - "end_line": 704, - "ast_sha": "9193c0ff46540e43a7aaaee2fb97ba681d059c86aaeb016437fd1a0df79bccb2", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "4cbf35396240ac6232f92e12fce80ad45787e5bc7dc910189d78498d1beae764", - "start_line": 703, - "name": "__stringify__", - "arity": 1 - }, - "subscribe_and_join!/2:352": { - "line": 352, - "guard": "is_binary(topic)", - "pattern": "%Phoenix.Socket{} = socket, topic", - "kind": "def", - "end_line": 353, - "ast_sha": "5449a73a921a28486e6b84273abe2805d243a4640706ae1f58c42fc72043fd71", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "42b3e8fc022aa11991192d44beee63a32fa1496b7e89be63b88f9d06cfe5fcc1", - "start_line": 352, - "name": "subscribe_and_join!", - "arity": 2 - }, - "push/3:472": { - "line": 472, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket, event, payload", - "kind": "def", - "end_line": 476, - "ast_sha": "a3e4e75773d64c8e97b25bd3b8e792ff8d912d4c2698fcf3296ad07c2cf9d2b3", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "3cc680af9db19de71b3750ec27aad630d8982e33bdddb6c11d4925305d3f2971", - "start_line": 472, - "name": "push", - "arity": 3 - }, - "socket/3:235": { - "line": 235, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 235, - "ast_sha": "ef90a6b17bb0b0f823cc47a7b5719008cedbafcd659d1763ce5a9a3d8a3b54f0", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "4fcd287e984381b4969811ab5cc8e0f23a961d42dd6954c786e91b7e66943176", - "start_line": 235, - "name": "socket", - "arity": 3 - }, - "socket/5:239": { - "line": 239, - "guard": null, - "pattern": "module, id, assigns, options, caller", - "kind": "defp", - "end_line": 251, - "ast_sha": "cbcb92a00dc8259c921507318d6a9b06de7e42627ec56a496c91a545c6e06f56", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "0a21c04bd1ccf0cbd5bfb76b0b75654ea4fcc4a3222bf216ec9e9770c8625ba6", - "start_line": 239, - "name": "socket", - "arity": 5 - }, - "broadcast_from/3:517": { - "line": 517, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket, event, message", - "kind": "def", - "end_line": 519, - "ast_sha": "d8d73246057b0eb79817be1485ce4e0e4c717b0920c0630276f51a946f4d461f", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "e08f1191f36670379588324ea1fa5578c295823e33d7d214567c7c649d1b7235", - "start_line": 517, - "name": "broadcast_from", - "arity": 3 - }, - "stringify_kv/1:708": { - "line": 708, - "guard": null, - "pattern": "{k, v}", - "kind": "defp", - "end_line": 709, - "ast_sha": "a82fb91e06f5de9f672bdd0611a733ac2c5223c22ac7810cd91220e11173a838", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "73992879ca84e8953c9cac3694c2c8136d2b68b18fa9ff0aaa86d83aa41f9c94", - "start_line": 708, - "name": "stringify_kv", - "arity": 1 - }, - "subscribe_and_join/2:378": { - "line": 378, - "guard": "is_binary(topic)", - "pattern": "%Phoenix.Socket{} = socket, topic", - "kind": "def", - "end_line": 379, - "ast_sha": "88fed2c43c5e5ebb1b4b1f941c3b845b32c7759c97cc81a44033ad7235d65825", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "ac5cf26fb286375d0a4a8e2b7d4b4e3d69e4a59ae75e9c705339258007fed796", - "start_line": 378, - "name": "subscribe_and_join", - "arity": 2 - }, - "assert_push/3:561": { - "line": 561, - "guard": null, - "pattern": "event, payload, timeout", - "kind": "defmacro", - "end_line": 565, - "ast_sha": "7128fda7a15bd465475134e4b03b17f60ff6864f0970bf4a1d5af0d1790758b0", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "91501f991edf29c99d5d057bd38e8e7b48967e356a5b13f355c32fc13c12bde0", - "start_line": 561, - "name": "assert_push", - "arity": 3 - }, - "__socket__/5:256": { - "line": 256, - "guard": null, - "pattern": "socket, id, assigns, endpoint, options", - "kind": "def", - "end_line": 265, - "ast_sha": "bca468eab7dfb97455431e087fa602248ebb2fc649c6d2a186e9f9025f16b3f6", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "122c56b025513626a36b831767c6b1fb2071cedb75c850e28c7134a69dd34979", - "start_line": 256, - "name": "__socket__", - "arity": 5 - }, - "subscribe_and_join/4:404": { - "line": 404, - "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", - "kind": "def", - "end_line": 407, - "ast_sha": "dccf9962c0cd9c060d3cbefa42574c876f822fa8c062436ef1446e321c2b4671", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "1bf2e7db59cd609cb9579221e4cb089eda218cba44d44f6ee17f3cccb5d5a30d", - "start_line": 404, - "name": "subscribe_and_join", - "arity": 4 - }, - "subscribe_and_join/3:383": { - "line": 383, - "guard": "is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, topic, payload", - "kind": "def", - "end_line": 385, - "ast_sha": "7c3531f413467e35e99d9443411ed9d25d8281112d667eb7dd35eccbab4809f2", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "a1d6fa78aa8075f7d3ea64aafe17c93079c5f65f1ac74f325b1a192449d53a10", - "start_line": 383, - "name": "subscribe_and_join", - "arity": 3 - }, - "__using__/1:177": { - "line": 177, - "guard": null, - "pattern": "_", - "kind": "defmacro", - "end_line": 186, - "ast_sha": "fbbf561bf066a2065d5e5cafab58d4d6c7f769788a82bb16dc56b19285df66d3", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "7cd4e4c479b66c1cb3a53a01521d19d77bbc6b581355415fe510d7fda7a7c4be", - "start_line": 177, - "name": "__using__", - "arity": 1 - }, - "__stringify__/1:705": { - "line": 705, - "guard": null, - "pattern": "other", - "kind": "def", - "end_line": 706, - "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "863b7454af46fca7b60ff5069047471fb473ea9795cbbe0d9f7c726cc0980fcf", - "start_line": 705, - "name": "__stringify__", - "arity": 1 - }, - "push/2:472": { - "line": 472, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 472, - "ast_sha": "e6f7cc4e18f7f6521a95a6dfd63f7fcbfd278ca01ea6e14b61b28019b4a161b5", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "7e70ea5113393916d1f45c1252768ea2d46e1f001d61467faf6f88782137629c", - "start_line": 472, - "name": "push", - "arity": 2 - }, - "leave/1:487": { - "line": 487, - "guard": null, - "pattern": "%Phoenix.Socket{} = socket", - "kind": "def", - "end_line": 488, - "ast_sha": "8523ce3d65c95d31a950b6a38ea8ec7e639ead3845b56d512d9343a04c5821e0", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "6885f0f2558399b5e0ffdfaf60c448860c215f7902a29171556275470a525c52", - "start_line": 487, - "name": "leave", - "arity": 1 - }, - "refute_reply/4:626": { - "line": 626, - "guard": null, - "pattern": "ref, status, payload, timeout", - "kind": "defmacro", - "end_line": 632, - "ast_sha": "9dc01cbaebd558572676e412967d133c768c2f94e9fa742f4b1cfa4f35747849", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "9ea9874b4e5b6ede0af859aa26944e93a3cb39cfc4a704eea881388f61f822d8", - "start_line": 626, - "name": "refute_reply", - "arity": 4 - }, - "socket/2:300": { - "line": 300, - "guard": null, - "pattern": "id, assigns", - "kind": "defmacro", - "end_line": 301, - "ast_sha": "97935aca95c9990d97f75765e1c7f37460b1eae74ae2682dbc79d162f7e061d0", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "83c4be91a8ca7a8a34282297938050bdc5ddb2c85632565de10086827546ebac", - "start_line": 300, - "name": "socket", - "arity": 2 - }, - "connect/2:310": { - "line": 310, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 310, - "ast_sha": "c7cb4ab995a062ecff873d2074f7dc0859b3b0ee341956c5beee454858e547b9", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "b1ba6f2f1f42270c09c4184b64851989723a1ee125459c7785a7cf0a9e23a477", - "start_line": 310, - "name": "connect", - "arity": 2 - }, - "subscribe_and_join!/4:369": { - "line": 369, - "guard": "is_atom(channel) and is_binary(topic) and is_map(payload)", - "pattern": "%Phoenix.Socket{} = socket, channel, topic, payload", - "kind": "def", - "end_line": 373, - "ast_sha": "11ba779714babf316a5558b08e469afd48192832e57d5052c86cf5ab5b1a109c", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "518723426fb0d2bc3d472e4c871b2edf17c9b1b7a3a032dd91fc3378fd096ad9", - "start_line": 369, - "name": "subscribe_and_join!", - "arity": 4 - }, - "assert_push/2:561": { - "line": 561, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 561, - "ast_sha": "1a4817a1d98e86caccd29794b8a6a9349e2c3a0bf84d83499ea42b7d15c3d42d", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "09d7a4a399efc212870baca6ef28ffce03d36acfe3c57abd7fb244d6022a2e28", - "start_line": 561, - "name": "assert_push", - "arity": 2 - }, - "socket/0:294": { - "line": 294, - "guard": null, - "pattern": "", - "kind": "defmacro", - "end_line": 295, - "ast_sha": "d03043df313a25291caf53e9dc0fc3a2b619a57c3f206555ceedb46e8c4537f7", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "af68f9db2d4814599b89386da51bc7a9be5067d96252333f256feb8ff204c62c", - "start_line": 294, - "name": "socket", - "arity": 0 - }, - "join/2:411": { - "line": 411, - "guard": "is_binary(topic)", - "pattern": "%Phoenix.Socket{} = socket, topic", - "kind": "def", - "end_line": 412, - "ast_sha": "31ca8ffe7b3b888ccc0c29dfdd911bc481aa56070efc2e78f1a4c900c78980f6", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "a717e13398f910a18d77c14d8ea5aa4cca54c093c4dc07b417fd81dde37d7eb7", - "start_line": 411, - "name": "join", - "arity": 2 - } - }, - "Phoenix.Transports.LongPoll": { - "broadcast_from!/3:246": { - "line": 246, - "guard": "is_binary(topic)", - "pattern": "endpoint, topic, msg", - "kind": "defp", - "end_line": 247, - "ast_sha": "890b25645d84fb258ff0cf484115ce5d14ba8062d9cfa07920585ee84fea0d05", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "a15fe8336045d6e69517c5ebb2c5aac58bd85e06a90d98372c0c4c535f6e2240", - "start_line": 246, - "name": "broadcast_from!", - "arity": 3 - }, - "broadcast_from!/3:249": { - "line": 249, - "guard": "is_pid(pid)", - "pattern": "_endpoint, pid, msg", - "kind": "defp", - "end_line": 250, - "ast_sha": "cd5c534c4cde053164cb27a14ed51e994a8927d64b63cb2803c4a0fa7efa2ca2", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "f6fcfd5a8ea9e6e0850517d542fd37da434ffb37f377abeecee923abde6b938c", - "start_line": 249, - "name": "broadcast_from!", - "arity": 3 - }, - "call/2:25": { - "line": 25, - "guard": null, - "pattern": "conn, {endpoint, handler, opts}", - "kind": "def", - "end_line": 32, - "ast_sha": "6ebba8351f12b476a934fcd9fea9e06249a31892f8ae3a564dfc0cabfff6a155", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "dca83e5e634826e19f47dd63786392952849ec7858ef74d29d18386c04964d89", - "start_line": 25, - "name": "call", - "arity": 2 - }, - "client_ref/1:231": { - "line": 231, - "guard": "is_binary(topic)", - "pattern": "topic", - "kind": "defp", - "end_line": 231, - "ast_sha": "5bb3c38d912680cb653db0f597424fd0b5c40073d822dfe470d89a0f9db122af", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "9325454a425ee5087fb0d6cec03c7f74a28a42b6603bcf27d95d4d67337a26fb", - "start_line": 231, - "name": "client_ref", - "arity": 1 - }, - "client_ref/1:232": { - "line": 232, - "guard": "is_pid(pid)", - "pattern": "pid", - "kind": "defp", - "end_line": 232, - "ast_sha": "f29b2ed947a6b88e9227df6493c7bb1dd125545fd0f695ce069723dbf3dd3105", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "6432a343173dacbdc7453fa921b8f9119ff52310181c0b24c7d067cecf648772", - "start_line": 232, - "name": "client_ref", - "arity": 1 - }, - "default_config/0:12": { - "line": 12, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 12, - "ast_sha": "e8a070ecb4f398f76a58fda9411442165845918f93c2aec27bbc22f1c046cc44", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "6975dacee86c58c3c40b7493f51c483a5c6cbf4638f425fdf46b56581003560f", - "start_line": 12, - "name": "default_config", - "arity": 0 - }, - "dispatch/4:35": { - "line": 35, - "guard": null, - "pattern": "%{halted: true} = conn, _, _, _", - "kind": "defp", - "end_line": 36, - "ast_sha": "410a16737bc218390963f2002f00bc57ae72f0f8938a1f70046d14b20cb8be45", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "2171e52d22529bacc627fed981185672aff91c5bc477cf0b10b6382bcb3fd62f", - "start_line": 35, - "name": "dispatch", - "arity": 4 - }, - "dispatch/4:41": { - "line": 41, - "guard": null, - "pattern": "%{method: \"OPTIONS\"} = conn, _, _, _", - "kind": "defp", - "end_line": 48, - "ast_sha": "153efd5d3004bf19673d69f162f296320d5af163a253f66d4796424a0fcaadce", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "fbd10a7059cfe8b9179fb2abcaf2244cf5f3da968952151962d6f165ad5813e6", - "start_line": 41, - "name": "dispatch", - "arity": 4 - }, - "dispatch/4:52": { - "line": 52, - "guard": null, - "pattern": "%{method: \"GET\"} = conn, endpoint, handler, opts", - "kind": "defp", - "end_line": 58, - "ast_sha": "44aa3287f9d3ab39c98214ad5528b5defeea9786811f56ddc579796d5da0a550", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "7bac0d50285bff876920d2b9406b698e0c6c11261fa5993bbae8513956d03f11", - "start_line": 52, - "name": "dispatch", - "arity": 4 - }, - "dispatch/4:63": { - "line": 63, - "guard": null, - "pattern": "%{method: \"POST\"} = conn, endpoint, _, opts", - "kind": "defp", - "end_line": 69, - "ast_sha": "551fed22c27516f22e59951e7fc70f88a8d8a9290cb69e5279c8bb83e5a124c5", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "49f07e8f5f76b080ee8f54359ab075a9fb981f0d74fffe0269c4fd1547da8704", - "start_line": 63, - "name": "dispatch", - "arity": 4 - }, - "dispatch/4:74": { - "line": 74, - "guard": null, - "pattern": "conn, _, _, _", - "kind": "defp", - "end_line": 75, - "ast_sha": "7f563dd08682b67a0723bd92547b9231b3c09e5ded63d460aeda42e94cba1bf1", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "93823b984420d59768cb5470e9f72d88cc15eee3c82fc3325c992853b0b3bba1", - "start_line": 74, - "name": "dispatch", - "arity": 4 - }, - "init/1:23": { - "line": 23, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 23, - "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", - "start_line": 23, - "name": "init", - "arity": 1 - }, - "listen/4:160": { - "line": 160, - "guard": null, - "pattern": "conn, server_ref, endpoint, opts", - "kind": "defp", - "end_line": 188, - "ast_sha": "8d88f6745f4d02833f376fbdd98acc084a70263c7f20eb438b08d502549b6727", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "57a2d4357574c212992ecfb836c893e74ff251de36f4f530060c4b4ad5ff5c9e", - "start_line": 160, - "name": "listen", - "arity": 4 - }, - "maybe_auth_token_from_header/2:270": { - "line": 270, - "guard": null, - "pattern": "conn, true", - "kind": "defp", - "end_line": 276, - "ast_sha": "418fd570780344c832392618fa5ebc86b57cf089e4d3f3be92d08dbb00348e95", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "fd657aac70fca7ad7d6fe7d76efdfd70acaf6db36998474650f6d89e46efc7db", - "start_line": 270, - "name": "maybe_auth_token_from_header", - "arity": 2 - }, - "maybe_auth_token_from_header/2:280": { - "line": 280, - "guard": null, - "pattern": "conn, _", - "kind": "defp", - "end_line": 280, - "ast_sha": "d418dff67505cf526abe380616091b9f20a1537b40a9770ff5b9292092c7c786", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "3465c5df608942102ca5a8d5c47d36aefaa005f81aec552c3d646fd73d7b2083", - "start_line": 280, - "name": "maybe_auth_token_from_header", - "arity": 2 - }, - "new_session/4:133": { - "line": 133, - "guard": null, - "pattern": "conn, endpoint, handler, opts", - "kind": "defp", - "end_line": 156, - "ast_sha": "262424b3455aa93115396aa917215de1fbd95939988f783ccdf4f265559a305c", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "24eaa8fbe28d0b8f2e024134aefa5cd3ec9f39b96181d8d83f5c30cfc66d9b04", - "start_line": 133, - "name": "new_session", - "arity": 4 - }, - "publish/4:78": { - "line": 78, - "guard": null, - "pattern": "conn, server_ref, endpoint, opts", - "kind": "defp", - "end_line": 107, - "ast_sha": "f6a2fcf93d7baadb013eff1f1c33b2897846d89e6de99e1ef86cf3a35427568e", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "b586f21319ac56c6b0e1cf1a87469f8a77b1a4b30c9dddcbdb8814cfb63b10b9", - "start_line": 78, - "name": "publish", - "arity": 4 - }, - "resume_session/4:193": { - "line": 193, - "guard": null, - "pattern": "%Plug.Conn{} = conn, %{\"token\" => token}, endpoint, opts", - "kind": "defp", - "end_line": 214, - "ast_sha": "897ae69b08b94b0ac4e79bc35ca56e6bed23cb7ac9f75a7fe79a268de300ab22", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "86e950de434c2b212acc4eec1858df1313137a0668be5fe9c932faa0172b47ec", - "start_line": 193, - "name": "resume_session", - "arity": 4 - }, - "resume_session/4:219": { - "line": 219, - "guard": null, - "pattern": "%Plug.Conn{}, _params, _endpoint, _opts", - "kind": "defp", - "end_line": 219, - "ast_sha": "4be6ee91cbca4d49e9f3458542a1b6b9b346ab56d719753bcce1f08cab538980", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "811dcc19d1de14d4a1931aafa3b09214934651b9a5a6390582baac4b5b653cb2", - "start_line": 219, - "name": "resume_session", - "arity": 4 - }, - "safe_decode64!/1:111": { - "line": 111, - "guard": null, - "pattern": "base64", - "kind": "defp", - "end_line": 115, - "ast_sha": "54ee7946a3a89117abba779f8df04ca9618f0b8c20febfcb61f8df5e7865ca9c", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "e60fbdd747120d67ae89933cb247fa6a1cd0b0818ac4366e8613cedad135ab22", - "start_line": 111, - "name": "safe_decode64!", - "arity": 1 - }, - "send_json/2:290": { - "line": 290, - "guard": null, - "pattern": "conn, data", - "kind": "defp", - "end_line": 293, - "ast_sha": "37b0d32c189d7e4ba0dd3011b0ad9921d019ade4428e7664d29468bf4471c26a", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "699f01e58e233a8e0e253d87139e3437de92fc4abba0e8c1dacec6ff61238a6a", - "start_line": 290, - "name": "send_json", - "arity": 2 - }, - "server_ref/4:223": { - "line": 223, - "guard": "is_pid(pid)", - "pattern": "endpoint_id, id, pid, topic", - "kind": "defp", - "end_line": 227, - "ast_sha": "1c99f00b45fdd0660e1fb20f379807df0e1f0943204a1c8c1517563bcfbfdb29", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "680c7920df406e95a188dbf11ca18d013f9518ba02719a0051f9c80d039ccfc9", - "start_line": 223, - "name": "server_ref", - "arity": 4 - }, - "sign_token/3:252": { - "line": 252, - "guard": null, - "pattern": "endpoint, data, opts", - "kind": "defp", - "end_line": 257, - "ast_sha": "176def848912098419fd5c45a16abec9a31fcd1ad3da505d8cf8d45913935985", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "0537dfb964d510605ad45f7f4ee98320e31a4158bcf1feae9f62c3ea64d5efc3", - "start_line": 252, - "name": "sign_token", - "arity": 3 - }, - "status_json/1:282": { - "line": 282, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 283, - "ast_sha": "b71ee2ebb5d3bcd89cb86662f133ca70018156aee8b94ecf169900fad21194d6", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "2c340f150529503fa855fedb251271e9e42017cc7e8927bb05fb9967dafee2a5", - "start_line": 282, - "name": "status_json", - "arity": 1 - }, - "status_token_messages_json/3:286": { - "line": 286, - "guard": null, - "pattern": "conn, token, messages", - "kind": "defp", - "end_line": 287, - "ast_sha": "5d9e1435c6cfe7abd27975540bc883d87fec7ff44572a3c1e62a23a6075af9ca", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "cc0ca9ba01f78b07567b7410db6579e5379be149eafd7f3e3e2e14df36fda25b", - "start_line": 286, - "name": "status_token_messages_json", - "arity": 3 - }, - "subscribe/2:234": { - "line": 234, - "guard": "is_binary(topic)", - "pattern": "endpoint, topic", - "kind": "defp", - "end_line": 235, - "ast_sha": "ce5a9bf43aa81b2d4863733d4ebb03efdc8f63184777f2f53266ff0ed58579fc", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "dcafa35e2faf014cc97ce70bbea56852439ccf0c79ec24c68efa1d1f42e58048", - "start_line": 234, - "name": "subscribe", - "arity": 2 - }, - "subscribe/2:237": { - "line": 237, - "guard": "is_pid(pid)", - "pattern": "_endpoint, pid", - "kind": "defp", - "end_line": 237, - "ast_sha": "5447a8e791c0f4f5d29fcbcd7acb171e1dd0ad30cd2a5cf9ba600815eb1c7582", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "ebf392a3c9f21ff8556f21036af302a3212e87c7e44ec2cda49cc1b8b320d799", - "start_line": 237, - "name": "subscribe", - "arity": 2 - }, - "transport_dispatch/4:119": { - "line": 119, - "guard": null, - "pattern": "endpoint, server_ref, body, opts", - "kind": "defp", - "end_line": 127, - "ast_sha": "6d89c4135eb889e2ebaa62672d039220c562c93991fe63b85c3717521e6d66f5", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "a9dafa5f6155d224d5e3e648b1a0d28b362c344bb247c9cbab490289baada6f1", - "start_line": 119, - "name": "transport_dispatch", - "arity": 4 - }, - "unsubscribe/2:240": { - "line": 240, - "guard": "is_binary(topic)", - "pattern": "endpoint, topic", - "kind": "defp", - "end_line": 241, - "ast_sha": "183a230562886472b79b50a1bdbceeb105dfb65adeed71439f10a6018bda684d", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "905d57b191f298005a871ebe86fe00aa41bb7fefa207207cf34784d346ea84bf", - "start_line": 240, - "name": "unsubscribe", - "arity": 2 - }, - "unsubscribe/2:243": { - "line": 243, - "guard": "is_pid(pid)", - "pattern": "_endpoint, pid", - "kind": "defp", - "end_line": 243, - "ast_sha": "d1c74e5f505222011cc2621376565b3a2da73dc59917f64c0c59309819de778d", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "4b0d8fb09d4cb5a7445357b1afc208cf6defb74190f96b468cc99d939bccdbd3", - "start_line": 243, - "name": "unsubscribe", - "arity": 2 - }, - "verify_token/3:261": { - "line": 261, - "guard": null, - "pattern": "endpoint, signed, opts", - "kind": "defp", - "end_line": 266, - "ast_sha": "71b9409e962ca4b67f3bb0113437b0a883e8b426c9b7f8db3cf6009958a9bd72", - "source_file": "lib/phoenix/transports/long_poll.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/long_poll.ex", - "source_sha": "df2a1794e91f1b26907f3c6a1f3e77bcad90c9469c37b720fe8f3de0baac69e0", - "start_line": 261, - "name": "verify_token", - "arity": 3 - } - }, - "Phoenix.Endpoint.Supervisor": { - "init/1:28": { - "line": 28, - "guard": null, - "pattern": "{otp_app, mod, opts}", - "kind": "def", - "end_line": 110, - "ast_sha": "437a2cb37a78d9d36ca74d37d6e202f7419745d35503d5e5ac9214543c918e4d", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "e428507a6754442cf8ef33d8642755e9eed138448ee330b9eeaa4831fb3870f0", - "start_line": 28, - "name": "init", - "arity": 1 - }, - "empty_string_if_root/1:392": { - "line": 392, - "guard": null, - "pattern": "other", - "kind": "defp", - "end_line": 392, - "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "c546479b480ce1ff0d55945d021d6884c0dd2fb52ce1c07079ed5477f1b1d717", - "start_line": 392, - "name": "empty_string_if_root", - "arity": 1 - }, - "server?/1:219": { - "line": 219, - "guard": "is_list(conf)", - "pattern": "conf", - "kind": "defp", - "end_line": 221, - "ast_sha": "4ec8d6168ba5e142b4757be616d54323b4f252ac80eb2fa525edf2ea8e438c40", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "91ebd2dae890c87c38dfac97e61f0396322f33559c4d4a814f7aef5be4fb2e85", - "start_line": 219, - "name": "server?", - "arity": 1 - }, - "server_children/3:182": { - "line": 182, - "guard": null, - "pattern": "mod, config, server?", - "kind": "defp", - "end_line": 197, - "ast_sha": "0eb8ebeae7304b6f65ac231c831948553a4bda8c14e30ff2742b19bab5013074", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "c83c1893217e3d7dc8a4ef0bb08949a2d954ed169b6c46545723aaf24c4e9afb", - "start_line": 182, - "name": "server_children", - "arity": 3 - }, - "config_children/3:173": { - "line": 173, - "guard": null, - "pattern": "mod, conf, default_conf", - "kind": "defp", - "end_line": 175, - "ast_sha": "8ea333adebcb34a0778eb74f4ebd5368706d11b339b285fbeeb13c2a7695e464", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "f26b29e3364650cf512ad4b85869cc3b79e799a99c420b89ee4eb6af967cac49", - "start_line": 173, - "name": "config_children", - "arity": 3 - }, - "static_cache/3:433": { - "line": 433, - "guard": null, - "pattern": "digests, value, true", - "kind": "defp", - "end_line": 434, - "ast_sha": "93ee799841760bc11e9e6fde9bd1d5880a594801f2ce884c81307d6ee20c413d", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "05c2e5bff0ac885e40b8a910a969ab7e041b51363411f23cf36bae7996382ea0", - "start_line": 433, - "name": "static_cache", - "arity": 3 - }, - "empty_string_if_root/1:391": { - "line": 391, - "guard": null, - "pattern": "\"/\"", - "kind": "defp", - "end_line": 391, - "ast_sha": "355f97ee86f192e98676e593626c55628410f8d89503582df461836864ab4f00", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "2a9c74084a9d7b5eaca921f5cba23890094308dda35106a4cc7a2b22b277acc1", - "start_line": 391, - "name": "empty_string_if_root", - "arity": 1 - }, - "start_link/3:12": { - "line": 12, - "guard": null, - "pattern": "otp_app, mod, opts", - "kind": "def", - "end_line": 23, - "ast_sha": "824fa0f310980fc9e136750d7e00d0b4d73cd3dcfbb17f0605f08cbdf931f96e", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "beef9447e54d63e614c4167a17b565259878e40e654bfa6640662f9f42b9f84a", - "start_line": 12, - "name": "start_link", - "arity": 3 - }, - "child_spec/1:7": { - "line": 7, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 543, - "ast_sha": "fc4089f59098af2b147c7156741d069df101c260a031bdfd9bac6deb22f97153", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "cf6ae509f6d58b1e655f57691748c7c8104d8d68166742572e3d372706e02437", - "start_line": 7, - "name": "child_spec", - "arity": 1 - }, - "render_errors/1:259": { - "line": 259, - "guard": null, - "pattern": "module", - "kind": "defp", - "end_line": 263, - "ast_sha": "e468c0df34c5c5aa7faee547658116da60be151aedc9cc0b4d72651776e65689", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "9a06d14b897730109103c593f2eac9ee038b5dde166bfbf3ac5af7d76a493a02", - "start_line": 259, - "name": "render_errors", - "arity": 1 - }, - "static_lookup/2:292": { - "line": 292, - "guard": null, - "pattern": "_endpoint, <<\"/\"::binary, _::binary>> = path", - "kind": "def", - "end_line": 296, - "ast_sha": "b6ee659363f81693964f01fea47c058449c04c292be284b443ebbc92eb224dea", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "b330c3365be56706750049afd89cfa369d89a0693c2d14aacdd2f9902171c795", - "start_line": 292, - "name": "static_lookup", - "arity": 2 - }, - "port_to_integer/1:315": { - "line": 315, - "guard": "is_integer(port)", - "pattern": "port", - "kind": "defp", - "end_line": 315, - "ast_sha": "3ffa153250cb67eaa24a5ddd12951e20dc5e68138311c00894e86b52593e5fdc", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "074f5f04a25e914d778ae0d21b26d1a362468488bf8979abbc0bab9ad5878c46", - "start_line": 315, - "name": "port_to_integer", - "arity": 1 - }, - "warmup_static/2:429": { - "line": 429, - "guard": null, - "pattern": "_endpoint, _manifest", - "kind": "defp", - "end_line": 430, - "ast_sha": "16da2ddc3c7691a490f0098e6e72db4e76d2336076ca439b0e43d5d404c44b61", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "45e9a118e8349238287cecf6abf38e7a4d7445be2c746e0cbc99291148382112", - "start_line": 429, - "name": "warmup_static", - "arity": 2 - }, - "host_to_binary/1:310": { - "line": 310, - "guard": null, - "pattern": "host", - "kind": "defp", - "end_line": 310, - "ast_sha": "fcc6e42a3178691cc48b853962a3394fe692fb40382672cd3ed333809f8bfc0e", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "5c1f211fed7786a4ce62803ec43b1ba6368132b8316e3013254c6cb6acf4d2dd", - "start_line": 310, - "name": "host_to_binary", - "arity": 1 - }, - "static_lookup/2:300": { - "line": 300, - "guard": "is_binary(path)", - "pattern": "_endpoint, path", - "kind": "def", - "end_line": 301, - "ast_sha": "d837217f8425affa302359b190fbd3b7cc3cafc991fe5fc331a38d153c542d6d", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "1046105d3a9f6b9c2a6572f3c844c6405996fd368fcb1aa994c9f4bc5c76b2e8", - "start_line": 300, - "name": "static_lookup", - "arity": 2 - }, - "port_to_integer/1:313": { - "line": 313, - "guard": null, - "pattern": "{:system, env_var}", - "kind": "defp", - "end_line": 313, - "ast_sha": "d41dcce49c4479fbd0c3c0cbb04ea812c31689deda8e54b4d7647f26fa8e8085", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "e3b91863e72be67bb9de16a0e26ee4de2d7463cc3e0d6b7c8756591f0b7fe557", - "start_line": 313, - "name": "port_to_integer", - "arity": 1 - }, - "apply_or_ignore/3:148": { - "line": 148, - "guard": null, - "pattern": "socket, fun, args", - "kind": "defp", - "end_line": 151, - "ast_sha": "8387c63c772eee2a4405a81495f2acee58f0ba5fd4cdb7abce60b534aeb751e8", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "f78051701607df65a6bf5cc2b768f90055316bacba5dce7cf95fd4772d8eac47", - "start_line": 148, - "name": "apply_or_ignore", - "arity": 3 - }, - "raise_invalid_path/1:304": { - "line": 304, - "guard": null, - "pattern": "path", - "kind": "defp", - "end_line": 305, - "ast_sha": "170fa5d96a379dc770b102d13b6e36ccace2fd2cf3064cc14a7445a177aedc27", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "790af0d8fe7812d232fc7bbcb05c6c5aed8aac6becd26197a9120c75a0bf070c", - "start_line": 304, - "name": "raise_invalid_path", - "arity": 1 - }, - "warmup_persistent/1:368": { - "line": 368, - "guard": null, - "pattern": "endpoint", - "kind": "defp", - "end_line": 387, - "ast_sha": "3538c58c267864f21e396ba8cd90f5df81ea5deb7ae8fa3cd99985e8508ee97e", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "bd8da5a66c77041a8efcc57ebc7fc1bd9dcb9bbcaed65d2933b68e96890197f0", - "start_line": 368, - "name": "warmup_persistent", - "arity": 1 - }, - "static_lookup/2:288": { - "line": 288, - "guard": null, - "pattern": "_endpoint, <<\"//\"::binary, _::binary>> = path", - "kind": "def", - "end_line": 289, - "ast_sha": "03ef91b0ce064d3605432c8b887c1bf2382e4df86d48b08e394dbc82993c79fe", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "4f0c13ae9c95e46fe24a683e71bba6d9cced20472a5f4a46c747ee41d3c15ff7", - "start_line": 288, - "name": "static_lookup", - "arity": 2 - }, - "warmup_static/2:418": { - "line": 418, - "guard": null, - "pattern": "endpoint, %{\"latest\" => latest, \"digests\" => digests}", - "kind": "defp", - "end_line": 424, - "ast_sha": "f3ac4a6430b8618cea5c97593c5ef5d83bc0f30d800727502b6e3d8ee0833f1e", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "502bec3d588803d917e467b880a3817fe8927d095b27d7d1eca1539c10cafdea", - "start_line": 418, - "name": "warmup_static", - "arity": 2 - }, - "watcher_children/3:202": { - "line": 202, - "guard": null, - "pattern": "_mod, conf, server?", - "kind": "defp", - "end_line": 206, - "ast_sha": "c0d43ccbae69b8be02adcfb21651b36c4dd7d6651f680ddf845e0fd884971b32", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "413493f0943ad85e8ce6f68cca0e890876b46b220940c31105a7f1a82720d852", - "start_line": 202, - "name": "watcher_children", - "arity": 3 - }, - "warmup_children/1:178": { - "line": 178, - "guard": null, - "pattern": "mod", - "kind": "defp", - "end_line": 179, - "ast_sha": "f138ec2522d89d76122db38fe6412bcfe0c91ec38fa81a791a421735a1764f22", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "d42942afe03d788797fb32740dd3c0b791f03da6d2cc90da3326dc977a599d74", - "start_line": 178, - "name": "warmup_children", - "arity": 1 - }, - "host_to_binary/1:309": { - "line": 309, - "guard": null, - "pattern": "{:system, env_var}", - "kind": "defp", - "end_line": 309, - "ast_sha": "32e927220b2f9e275dbf1ee80370b484c47df819dc63cc7a801a4d4112c01377", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "06135c36fd39f1fdbe33ca15c51ff20ed357624a256b594b48cdc7b7ab67f9ee", - "start_line": 309, - "name": "host_to_binary", - "arity": 1 - }, - "static_integrity/1:442": { - "line": 442, - "guard": null, - "pattern": "sha", - "kind": "defp", - "end_line": 442, - "ast_sha": "30a9e319d223188f3591de9179478fd88e7358ff26ba12a1c619aa07ff071ab0", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "b6dcd275cf5ef9507c297fba962d07e0d770d41c622e66a8c613ed7ae19a6968", - "start_line": 442, - "name": "static_integrity", - "arity": 1 - }, - "config_change/3:269": { - "line": 269, - "guard": null, - "pattern": "endpoint, changed, removed", - "kind": "def", - "end_line": 272, - "ast_sha": "c9b7d3a94d7e1783eb3e3ab2342c89e248b038e44da5eaec7033431c15f4aeee", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "62b82e1cf5e6450db8082e176cac16a447769ae36adb5b5494483866ec9a6159", - "start_line": 269, - "name": "config_change", - "arity": 3 - }, - "build_url/2:394": { - "line": 394, - "guard": null, - "pattern": "endpoint, url", - "kind": "defp", - "end_line": 415, - "ast_sha": "5286aac7970373d095819d163d3054b8dec510c92097bfa15a562e43ea0df7d0", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "080360e0a41b53b23b8b1e8b2554aeab3dcfb84e96662a0760084931ef106146", - "start_line": 394, - "name": "build_url", - "arity": 2 - }, - "start_link/2:12": { - "line": 12, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 12, - "ast_sha": "cafb953ce5db1f101c82de661d54995c64205e4206978c35644faf2bf3679f49", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "2eeb3b649a27af6def9ae6d4e1b080af5af23fff11ad5cd9a9a81ed2d66ee8f4", - "start_line": 12, - "name": "start_link", - "arity": 2 - }, - "server?/2:215": { - "line": 215, - "guard": "is_atom(otp_app) and is_atom(endpoint)", - "pattern": "otp_app, endpoint", - "kind": "def", - "end_line": 216, - "ast_sha": "502df6aa5eb6c58610c4b46186e72f46b8f4b887b260bc37681845a96bdc4794", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "f59c201163a7b8b32229817761e7d82fdb8029dd85db93ae3117836b1d4c3e4b", - "start_line": 215, - "name": "server?", - "arity": 2 - }, - "static_cache/3:437": { - "line": 437, - "guard": null, - "pattern": "digests, value, false", - "kind": "defp", - "end_line": 438, - "ast_sha": "1ac44d3799accf6bdc5df09932aed0c63ffe4e9450dddf83dba4a72d51d22256", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "7e5f1046566c22663c0ffbc60afdac0b0b5dcefd3e10338b46141e43b9b3fb2a", - "start_line": 437, - "name": "static_cache", - "arity": 3 - }, - "defaults/2:225": { - "line": 225, - "guard": null, - "pattern": "otp_app, module", - "kind": "defp", - "end_line": 232, - "ast_sha": "06ee4eedb27ccbb6be7bd504c68d64364c8910f002224283a9678dc00090b600", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "a9b8d10fa17693c98a426edf3f1b07dde5573001f2f704aa4bf7fdfae680c378", - "start_line": 225, - "name": "defaults", - "arity": 2 - }, - "static_integrity/1:441": { - "line": 441, - "guard": null, - "pattern": "nil", - "kind": "defp", - "end_line": 441, - "ast_sha": "1e9c973a157800df29e20529ffde676e6a5b78f28751532e823d484235666dce", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "8cf25c3cf6b4ae8472af33ff676ad078686637102fe4ea084ebd07eb80c3014b", - "start_line": 441, - "name": "static_integrity", - "arity": 1 - }, - "port_to_integer/1:314": { - "line": 314, - "guard": "is_binary(port)", - "pattern": "port", - "kind": "defp", - "end_line": 314, - "ast_sha": "db5cc62705a108c962a65eed482d322d2c088187c9eac8bca6cb97df4a250d75", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "506fdff094b92b11c5e6bdcbb576f85d8a5503d1d0084c38d965017cec596895", - "start_line": 314, - "name": "port_to_integer", - "arity": 1 - }, - "browser_open/2:474": { - "line": 474, - "guard": null, - "pattern": "endpoint, conf", - "kind": "defp", - "end_line": 485, - "ast_sha": "a1d436e47db6287a78da03438207a4e530892e7c0830eecf0db98ba1d38d6172", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "7aa96161f5da7834d412384a9ab7dc256f1b872eec43d95a3461f2f1c3894acf", - "start_line": 474, - "name": "browser_open", - "arity": 2 - }, - "pubsub_children/2:113": { - "line": 113, - "guard": null, - "pattern": "mod, conf", - "kind": "defp", - "end_line": 133, - "ast_sha": "b457296998162e645e9600c35ecefe495a6ddc400c1fdaeb19ca643fd147f53c", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "9d60f9f76f2c0ac260e2baa793c2aa4ea27b012432cb7141cec283ea37003aaf", - "start_line": 113, - "name": "pubsub_children", - "arity": 2 - }, - "cache_static_manifest/1:444": { - "line": 444, - "guard": null, - "pattern": "endpoint", - "kind": "defp", - "end_line": 459, - "ast_sha": "aa2d56314b10751cac425371741bf0a342f44597e19fbdd94d94a01c54fe1ffa", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "c7ca8b055d7bb6ab93df801f7689bc018e3b227f16342075ea349bd0ff90d4f0", - "start_line": 444, - "name": "cache_static_manifest", - "arity": 1 - }, - "warn_on_deprecated_system_env_tuples/4:317": { - "line": 317, - "guard": null, - "pattern": "otp_app, mod, conf, key", - "kind": "defp", - "end_line": 342, - "ast_sha": "b05d2223b241629c7c7e6ccd43c6a5292b5937e2fd5dd8f3b40d83ab6c4dee68", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "34d01600dd28c18e1c9a23ae145bea7eb869536915572f148df6acd7f3ce60a5", - "start_line": 317, - "name": "warn_on_deprecated_system_env_tuples", - "arity": 4 - }, - "warmup/1:351": { - "line": 351, - "guard": null, - "pattern": "endpoint", - "kind": "def", - "end_line": 359, - "ast_sha": "8724c0a3dddcca8ad3104693e40f396a43bdbd59b06b460896d3e17ec6ea2582", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "129fe72477fbab12f3a0c24a7cbdde88c0dd99e4776c2f882e05b54c9bdd1540", - "start_line": 351, - "name": "warmup", - "arity": 1 - }, - "log_access_url/2:468": { - "line": 468, - "guard": null, - "pattern": "endpoint, conf", - "kind": "defp", - "end_line": 470, - "ast_sha": "db66bf9eded7009d32855105e0067e90e97b33fb88531022ddcb4a46f788a515", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "219b723eb9339535548704c48349be7fff45d2b3b3bd1d5663267dfb68c94d56", - "start_line": 468, - "name": "log_access_url", - "arity": 2 - }, - "socket_children/3:139": { - "line": 139, - "guard": null, - "pattern": "endpoint, conf, fun", - "kind": "defp", - "end_line": 144, - "ast_sha": "07d4b51c8cb8b3c3aa17448031c0653be87350ab8149f1d667a8a1932bdecf0b", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "861df0fa8d3cec1eadc502e5d2b1a429159415765c0293736b28fbf81892a44a", - "start_line": 139, - "name": "socket_children", - "arity": 3 - }, - "check_origin_or_csrf_checked!/2:157": { - "line": 157, - "guard": null, - "pattern": "endpoint_conf, socket_opts", - "kind": "defp", - "end_line": 168, - "ast_sha": "409b994f86f1b81ab8c3a363ebf2a0c5243edadd04c61cbd813c4e2b5bdf1cc8", - "source_file": "lib/phoenix/endpoint/supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/supervisor.ex", - "source_sha": "d2d1ae88bcbcb46c851fb7929f6e6cee88858ca02d9fb26778271e9d03602cb1", - "start_line": 157, - "name": "check_origin_or_csrf_checked!", - "arity": 2 - } - }, - "Mix.Tasks.Phx.Gen.Secret": { - "invalid_args!/0:33": { - "line": 33, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 34, - "ast_sha": "ac8aba55bc9e914764ee7241f4e0726d3ba526af43804596ebee7be7142f1ab4", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "97ebfe76dd462d0119acdf9198aef34ccd51fbb721c21fb6c0451a854791f1b0", - "start_line": 33, - "name": "invalid_args!", - "arity": 0 - }, - "parse!/1:20": { - "line": 20, - "guard": null, - "pattern": "int", - "kind": "defp", - "end_line": 23, - "ast_sha": "7f6970802a324c0733e6fbb0a42e5a908e7247a8b7e9695668eb43b5d578bf65", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "6d7b111826cc6b57d9b404144026fd3a96a1f1bc9cb9ce25c2088578d21f0307", - "start_line": 20, - "name": "parse!", - "arity": 1 - }, - "random_string/1:27": { - "line": 27, - "guard": "length > 31", - "pattern": "length", - "kind": "defp", - "end_line": 28, - "ast_sha": "7f587bd97fa01da6cc93c79851d3440ed7320e1423bc2d233330ad6f5050bdd4", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "4747f00851adcea08c0bcea8fe34c0f4dce6a9c59870ab93dbda2ba70cc61116", - "start_line": 27, - "name": "random_string", - "arity": 1 - }, - "random_string/1:30": { - "line": 30, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 30, - "ast_sha": "3cf69dd38986280d271ca211a07635d4e05f8a4b822b01ab284c21281c26e5f2", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "3a4cf7c9e46b8a2b06cde069d53bd23f1a7bf4c73de45c56882c9e861f2817e4", - "start_line": 30, - "name": "random_string", - "arity": 1 - }, - "run/1:16": { - "line": 16, - "guard": null, - "pattern": "[]", - "kind": "def", - "end_line": 16, - "ast_sha": "495e019cfb92b9acc9d4f44c90eb6cd719ac2c2a7cd9ecd724a2d55fd3bca279", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "03576cd8aa7daf37637d7867f227f561c1d7730a51f3eef36aaa59b47fcd757e", - "start_line": 16, - "name": "run", - "arity": 1 - }, - "run/1:17": { - "line": 17, - "guard": null, - "pattern": "[int]", - "kind": "def", - "end_line": 17, - "ast_sha": "7e6051eb3353159488a18104b4eb1ca0bd54c05a578b246cef8bcc5dc5c0f944", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "910cf0ba6c184979bddeaddfd3f04a0cf8da11114420e939fcf991b96ac397c4", - "start_line": 17, - "name": "run", - "arity": 1 - }, - "run/1:18": { - "line": 18, - "guard": null, - "pattern": "[_ | _]", - "kind": "def", - "end_line": 18, - "ast_sha": "b315480f7c5d7bf47260f7b801aaf676e0f89c258aae37ef882376b4caad3944", - "source_file": "lib/mix/tasks/phx.gen.secret.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.secret.ex", - "source_sha": "71fc1519ff0da8256aeee0cd62bb861acecb594a0449f2d50da02ac79941905a", - "start_line": 18, - "name": "run", - "arity": 1 - } - }, - "Phoenix.ChannelTest.NoopSerializer": { - "decode!/2:173": { - "line": 173, - "guard": null, - "pattern": "message, _opts", - "kind": "def", - "end_line": 173, - "ast_sha": "c04be04cb42c8dde80aa7b1351a0bdd519e2ff03c6a8c368d6ebdeee74d62b48", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "6b5aba4a6a344baa3f8ab7fdd8a907554f8f9c95b4ea9113f6b7353bd9cda0bf", - "start_line": 173, - "name": "decode!", - "arity": 2 - }, - "encode!/1:171": { - "line": 171, - "guard": null, - "pattern": "%Phoenix.Socket.Reply{} = reply", - "kind": "def", - "end_line": 171, - "ast_sha": "bcf140b2e6029e5d5531cb15c50ff21aaf083b28b71e7443b9a8394463dcbe3f", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "5b9c14cb002e13aaa461f8453e2cfe9dbe92583242d50c72f696debac3f6f4c8", - "start_line": 171, - "name": "encode!", - "arity": 1 - }, - "encode!/1:172": { - "line": 172, - "guard": null, - "pattern": "%Phoenix.Socket.Message{} = msg", - "kind": "def", - "end_line": 172, - "ast_sha": "94dd986ef05fd6506424136c448f8ee7a15bea7343eca32137d127aa76c76c12", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "656caac21aa344c37d1abac6a3b27731a8d32efe3b0aa1f82c43904298dd5867", - "start_line": 172, - "name": "encode!", - "arity": 1 - }, - "fastlane!/1:163": { - "line": 163, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{} = msg", - "kind": "def", - "end_line": 167, - "ast_sha": "c199eb4850cd53b34b1bd8c438207dddd91fff386f2ba5473f14bc100243d9fd", - "source_file": "lib/phoenix/test/channel_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/channel_test.ex", - "source_sha": "846e6c32cd882ab865aaf0b5635ba409532d21fb203ce714fecc5ac954577365", - "start_line": 163, - "name": "fastlane!", - "arity": 1 - } - }, - "Phoenix.Router": { - "post/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "0e59357ddfef3bee1af4b07cff8c5efb5148b24be8f28fa9cde9c51612cd22b1", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "post", - "arity": 4 - }, - "scope/3:1097": { - "line": 1097, - "guard": null, - "pattern": "path, options, [do: context]", - "kind": "defmacro", - "end_line": 1115, - "ast_sha": "90a8f20a2c840737ee1a7cfe2e15ffef3019c2b17a8cbbeb16e39dd88fafd299", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "7af90d3810d149dd7d468616923fb329100817f9215f851ec6bd41239fecf01d", - "start_line": 1097, - "name": "scope", - "arity": 3 - }, - "scope/2:1070": { - "line": 1070, - "guard": null, - "pattern": "options, [do: context]", - "kind": "defmacro", - "end_line": 1078, - "ast_sha": "99a29b86a629491a2bcd8cb781cef988813e30f189c3dec4177cb9c509854a9f", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "43d3e2d03c37268853933ec41af0bf6cb4519af302304bd2828169304c005f54", - "start_line": 1070, - "name": "scope", - "arity": 2 - }, - "plug/1:828": { - "line": 828, - "guard": null, - "pattern": "x0", - "kind": "defmacro", - "end_line": 828, - "ast_sha": "aad9102eb389ee539b38e9dd07453ea6d271b2a04434d05298a15f0a6be17bd7", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "566f97ce1b8ef8b2037a65501fd516896ef4887adb316b93b0fff31fe1a371da", - "start_line": 828, - "name": "plug", - "arity": 1 - }, - "trace/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "12298e8c5cd6e0a43386bc4e650c01ff9340923edc3ee4e473da56429f80e25f", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "trace", - "arity": 4 - }, - "__call__/5:396": { - "line": 396, - "guard": null, - "pattern": "%{private: %{phoenix_bypass: :all}} = conn, metadata, prepare, _, _", - "kind": "def", - "end_line": 397, - "ast_sha": "41db49b45ed67e0a35a1c8cbe0cfb6d614cf8b5166b8ec2fe1f712db3df10c4f", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "04acb2eb559f6ff70601d3ffdbd632d3e14439f0ea44a8196b6b45897a1ba1a7", - "start_line": 396, - "name": "__call__", - "arity": 5 - }, - "__before_compile__/1:488": { - "line": 488, - "guard": null, - "pattern": "env", - "kind": "defmacro", - "end_line": 564, - "ast_sha": "02f546bead18749ba91e0a5057127e9ee632cdff587461187719f6b21ca539ca", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "656b4ae42ae7691f7f03df1e9e511b06b4d2c7cf940b680e1453a378aef328f3", - "start_line": 488, - "name": "__before_compile__", - "arity": 1 - }, - "routes/1:1228": { - "line": 1228, - "guard": null, - "pattern": "router", - "kind": "def", - "end_line": 1229, - "ast_sha": "d8b092fd3517df646a8c17cd97e97de4cf65d11d6ebed356772e43956ab8f13c", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "e5a61fd4fc4c829d5f12b98765a89c4efcc86c980dd045f300a4ad665abb1a97", - "start_line": 1228, - "name": "routes", - "arity": 1 - }, - "resources/2:1017": { - "line": 1017, - "guard": null, - "pattern": "path, controller", - "kind": "defmacro", - "end_line": 1018, - "ast_sha": "539036293a43b8e08d6b6e67496e80adf789ab5d02c081dfe805bb22baee0898", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "bc61f3f2f0534f5306816bb3d5b1bdb7547ad26134734ffdf5554258b9cd8eec", - "start_line": 1017, - "name": "resources", - "arity": 2 - }, - "forward/3:1216": { - "line": 1216, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 1216, - "ast_sha": "e347a86279e393b879e18977a0e7f95fb8676e8c191fe59d6ff3fee99c630244", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "eda0d06da0bb3c8f94779d1aac43923954ce797908365238c6dc2cd1f19014e2", - "start_line": 1216, - "name": "forward", - "arity": 3 - }, - "add_route/6:738": { - "line": 738, - "guard": null, - "pattern": "kind, verb, path, plug, plug_opts, options", - "kind": "defp", - "end_line": 748, - "ast_sha": "f37d0b447e8c5393ebaa90052a568382d2065b8742de1d047cf996754b86367f", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "19080d062522e17be12a0123d40d99e29633f8ad4a5daa7e0597282541709114", - "start_line": 738, - "name": "add_route", - "arity": 6 - }, - "resources/4:999": { - "line": 999, - "guard": null, - "pattern": "path, controller, opts, [do: nested_context]", - "kind": "defmacro", - "end_line": 1000, - "ast_sha": "15889f6f0dde38d0180ae4f6b066a145364b4748b2c45b1451dcccfb057dab82", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "d39fcf025da183dfb36b610bf35885b9211dc3557c998b87846c25aef3c2de00", - "start_line": 999, - "name": "resources", - "arity": 4 - }, - "build_verify/2:568": { - "line": 568, - "guard": null, - "pattern": "path, routes_per_path", - "kind": "defp", - "end_line": 588, - "ast_sha": "d7025feb4794c3a853371e6059b72e1cac9f41cb64dbbcd13730e9edf88c81b1", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "f4ce920d62822de96267c68c5f4ada99b25aa130e13f57cc679b7c80e46cb10a", - "start_line": 568, - "name": "build_verify", - "arity": 2 - }, - "__call__/5:400": { - "line": 400, - "guard": null, - "pattern": "conn, metadata, prepare, pipeline, {plug, opts}", - "kind": "def", - "end_line": 436, - "ast_sha": "30ecba9dcac699093141e68f7bccf015d08a6a997345bcca0c0600289a648ff3", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "6a5c1bb0425a57b2275e12851e65dffd0365d55600c3bac408e27da030f95167", - "start_line": 400, - "name": "__call__", - "arity": 5 - }, - "connect/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "63beb90ed591a4a2fd57a166458013161ee8b716528af99896c6bcd2fd0350c8", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "connect", - "arity": 3 - }, - "scoped_path/2:1180": { - "line": 1180, - "guard": null, - "pattern": "router_module, path", - "kind": "def", - "end_line": 1181, - "ast_sha": "06d1585a620ed35a0c4c558063c112db2c9d4d080524a309cc93a8485cda0659", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "10d0232a55851fbc85e5ed7af5228391e67c5cf8e3d07b0dc509200514878bca", - "start_line": 1180, - "name": "scoped_path", - "arity": 2 - }, - "build_pipes/2:663": { - "line": 663, - "guard": null, - "pattern": "name, pipe_through", - "kind": "defp", - "end_line": 669, - "ast_sha": "4dc13add9e8dbd23917fc0e8d76da71ab7df789f9c99e56ee5dc2f21a71daf06", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "ff662dcd1d075ca73261a1cc5450b4eb80ef5c672ad1e813a0ce92d5acd2fee0", - "start_line": 663, - "name": "build_pipes", - "arity": 2 - }, - "resources/3:1010": { - "line": 1010, - "guard": null, - "pattern": "path, controller, opts", - "kind": "defmacro", - "end_line": 1011, - "ast_sha": "671cc4600d56780ef93c788ea5627473f2a346ac34e4ea3d550c0c0f1d6ce609", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "8c401acd4d34ad091fd1932c3ddb943de3d77d12ba159c2ecd57607f63f0407b", - "start_line": 1010, - "name": "resources", - "arity": 3 - }, - "resources/3:1006": { - "line": 1006, - "guard": null, - "pattern": "path, controller, [do: nested_context]", - "kind": "defmacro", - "end_line": 1007, - "ast_sha": "5f55b59bd97696521707c9b2ec937edf7ad197a95ab3c660835f034433ba46c6", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "3435ca2a8ddca26cde9364ebcfe11e29709e022b6e51cfa8e338ceb16133028b", - "start_line": 1006, - "name": "resources", - "arity": 3 - }, - "pipeline/2:775": { - "line": 775, - "guard": null, - "pattern": "plug, [do: block]", - "kind": "defmacro", - "end_line": 816, - "ast_sha": "e4a183610dfd5e8868a2c452368d6eecb87107ae982686f177f65a6d457a9c76", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "2868a27400e0532f7af6ddb375179f585884958088978def4fdc9a955a3a6456", - "start_line": 775, - "name": "pipeline", - "arity": 2 - }, - "head/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "6b3d8695486de354938c49d36e5334ae25ce2600fe94a0216b7b4d6d0c8ed76b", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "head", - "arity": 4 - }, - "__verified_route__?/2:1313": { - "line": 1313, - "guard": null, - "pattern": "router, split_path", - "kind": "def", - "end_line": 1330, - "ast_sha": "db16dce3ecdf3a77dab51fbfcec7045a74edbbd9d69bc4404fdcb2f42de5dd8d", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "0eb070c41ed5597253bbe12ad7e0d905aac1c75ada3472e031cfe39b5baace62", - "start_line": 1313, - "name": "__verified_route__?", - "arity": 2 - }, - "prelude/1:297": { - "line": 297, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 312, - "ast_sha": "567715972e028612db0468f69f056f7be090320aaa585d5c28596d110eb2c134", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "418fd5a5f9a0bcb6a2ecf09b44820c3acd827110d897ef6151a2591250ffd2f9", - "start_line": 297, - "name": "prelude", - "arity": 1 - }, - "match_dispatch/0:441": { - "line": 441, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 441, - "ast_sha": "2e49f3567fbca82331c87402df68cedbaca54e8a2c351461d76958f4ad07f38e", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "8af58e20d8a2b4fe1d24c0bc1b7c6340f857d99c8c19080215c964951999bae2", - "start_line": 441, - "name": "match_dispatch", - "arity": 0 - }, - "patch/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "8f47cf5e3d667575fa1ef6ad651966c3fb79aa99948e64c73d9a8e5b86d2ae60", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "patch", - "arity": 4 - }, - "match/5:709": { - "line": 709, - "guard": null, - "pattern": "verb, path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 710, - "ast_sha": "ad85657425e03ff6f7282d434473bb9b458fae5f18184b54c776bbfaeff34033", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "56330fd4896917ae74d8df1173fd2205385574d2b69bb64e9a3ac75a0247c396", - "start_line": 709, - "name": "match", - "arity": 5 - }, - "options/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "dc6c0db4158027e638811a79a8ae2373ea9b7b54f154fdd3a1072b4d3b51ef1a", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "options", - "arity": 3 - }, - "get/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "c119cdc66c1e8fae8d571d1db11bd1f6c8c99822487997cafb37c79e7036848e", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "get", - "arity": 3 - }, - "match/4:709": { - "line": 709, - "guard": null, - "pattern": "x0, x1, x2, x3", - "kind": "defmacro", - "end_line": 709, - "ast_sha": "48ab80f9a30dbe4d63edd8f44195e742cb78f74eb5e9ad5c688c5bc7fb0ad5aa", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "af0f2afea612f74694623d64e359d0129d5fab6a8fbd7fac5e73a3281e47d3b4", - "start_line": 709, - "name": "match", - "arity": 4 - }, - "build_match_pipes/3:621": { - "line": 621, - "guard": null, - "pattern": "route, acc_pipes, known_pipes", - "kind": "defp", - "end_line": 632, - "ast_sha": "5f6853c8f6e8688590efc171c1d66498007127985788b6eb2eeb9de5693cd608", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "a9380e8e7763795ddbf9c6dd28b81806f79f22254dd111df3f3812fee7043909", - "start_line": 621, - "name": "build_match_pipes", - "arity": 3 - }, - "__using__/1:288": { - "line": 288, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 293, - "ast_sha": "c8d90b225bc1a3c07bcf9d22f805a31d2b451249a717df2cd623a4a973685192", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "f03024267e0919734b75c89c96d08ec575c5ec621dd46381db7c5a5ff1778adf", - "start_line": 288, - "name": "__using__", - "arity": 1 - }, - "forward/4:1216": { - "line": 1216, - "guard": null, - "pattern": "path, plug, plug_opts, router_opts", - "kind": "defmacro", - "end_line": 1221, - "ast_sha": "6008ad8a4dfd883d4d75e954b59940458eaf88ced4fd7611807fb9a880d61ed0", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "489de9848694acaab0edce86512f8d746c9dca765e6f8a1341be827396bb9ae5", - "start_line": 1216, - "name": "forward", - "arity": 4 - }, - "build_match/2:594": { - "line": 594, - "guard": null, - "pattern": "{route, expr}, {acc_pipes, known_pipes}", - "kind": "defp", - "end_line": 618, - "ast_sha": "cdaf15f1397eba1ec399c29156993322a652331a22429fd3d1bd4732fc3e2eca", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "e04f778801f7a06b25629f120b84ee74de8c3b97c0c069124e8953eb50a0b4f6", - "start_line": 594, - "name": "build_match", - "arity": 2 - }, - "do_scope/2:1147": { - "line": 1147, - "guard": null, - "pattern": "options, context", - "kind": "defp", - "end_line": 1152, - "ast_sha": "af9888494e03c1dc61ac8694080388705911e13f625049205ab3f1d0ec7bd668", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "877433aad2e1ee6e5e394d45a321905dc33e9394165826f622ffdc1e999925a0", - "start_line": 1147, - "name": "do_scope", - "arity": 2 - }, - "options/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "e15cff8d08202b5882f84dcf43f1b894d9781215f166aa622cf0021e7ebe5f05", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "options", - "arity": 4 - }, - "patch/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "45b9a1b7c3e9e831b553b86176e4993adf206572a6dc07408db61e5ab455e4c1", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "patch", - "arity": 3 - }, - "pipe_through/1:904": { - "line": 904, - "guard": null, - "pattern": "pipes", - "kind": "defmacro", - "end_line": 916, - "ast_sha": "871c6453dafd4c5bc4f0bb6a6083d6271911e3597eaca2e4006ad780ed9989d5", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "eda3b8fecb8801039e6e766e0c5c5dafcc55b885d826df583ee95efdc00e200a", - "start_line": 904, - "name": "pipe_through", - "arity": 1 - }, - "connect/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "e2f4a8a2e485da18f1be3f6862242c7e562740c53e6db6d784ea8e6ebabb905e", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "connect", - "arity": 4 - }, - "route_info/4:1267": { - "line": 1267, - "guard": "is_list(split_path)", - "pattern": "router, method, split_path, host", - "kind": "def", - "end_line": 1270, - "ast_sha": "19aa0324df8adce38477aa59ae4d172fe88ff3ab3b1b7098b010659c59f64189", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "a1202624790a76e5edaf304dba7f3994c68c895ae5552ed59cd0c549d17fe38b", - "start_line": 1267, - "name": "route_info", - "arity": 4 - }, - "expand_alias/2:863": { - "line": 863, - "guard": null, - "pattern": "other, _env", - "kind": "defp", - "end_line": 863, - "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", - "start_line": 863, - "name": "expand_alias", - "arity": 2 - }, - "defs/0:321": { - "line": 321, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 321, - "ast_sha": "8fd9a259c1471681b8fffb18681ddb569d151e7f8028e239c8befbb4984c2d01", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "0e059e9f76e9129199db5ba3543a3e66c7f1c9859ea82283efee6d093e976015", - "start_line": 321, - "name": "defs", - "arity": 0 - }, - "head/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "1f90ac08eeeb4fda484f76ab0a2e652765e4ce796ca72087c7dead7d68e32d11", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "head", - "arity": 3 - }, - "scoped_alias/2:1172": { - "line": 1172, - "guard": null, - "pattern": "router_module, alias", - "kind": "def", - "end_line": 1173, - "ast_sha": "4cc94f133766c4cb8192fed33bfc0290f442e0060cf8e7196e42d288efcf21d0", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "decd30169223f82e090eaa8f2eb2b7f7c9a15eb3146e5cc744cf823e150a4d03", - "start_line": 1172, - "name": "scoped_alias", - "arity": 2 - }, - "__formatted_routes__/1:1275": { - "line": 1275, - "guard": null, - "pattern": "router", - "kind": "def", - "end_line": 1305, - "ast_sha": "02abe097d03394bb882beea218e6452e84a3a3c4cbacc297267e20c014c654fa", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "32bc69459a6918576cca274a6e152fb21074f5ccafa61d58ec7957e30b76f44d", - "start_line": 1275, - "name": "__formatted_routes__", - "arity": 1 - }, - "__call__/5:381": { - "line": 381, - "guard": null, - "pattern": "%{private: %{phoenix_router: router, phoenix_bypass: {router, pipes}}} = conn, metadata, prepare, pipeline, _", - "kind": "def", - "end_line": 392, - "ast_sha": "44a9a06e13fa376194f571748f6794119093fa9262d86407711994b41331eab9", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "ddf8f4cb5ba0e5fe76669cbdf84326d9e39aad9c263bf1db70df94d680565fb5", - "start_line": 381, - "name": "__call__", - "arity": 5 - }, - "forward/2:1216": { - "line": 1216, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 1216, - "ast_sha": "d9dc0ea4147bc9c29b31d5a205a6ff27435da4fbea45cc9f3e0134339fc7a868", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "eda0d06da0bb3c8f94779d1aac43923954ce797908365238c6dc2cd1f19014e2", - "start_line": 1216, - "name": "forward", - "arity": 2 - }, - "build_metadata/2:636": { - "line": 636, - "guard": null, - "pattern": "route, path_params", - "kind": "defp", - "end_line": 654, - "ast_sha": "12094b7ee8dc4d746ad08e6ed26bd8f6c8436284336b235ac9e80541c6778f2c", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5cdccf27498f6af6785017b71e11aa240549643dd5992cad0a3d7467564328b9", - "start_line": 636, - "name": "build_metadata", - "arity": 2 - }, - "build_pipes/2:657": { - "line": 657, - "guard": null, - "pattern": "name, []", - "kind": "defp", - "end_line": 659, - "ast_sha": "27734ae7a8cfefb15a381a31eb315884d5f42d41f2fb123c16f95df5ab2687da", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "fa9633370095bd51fcab5db0bf4acc781e3afa1b904b87a43e88a673a603684f", - "start_line": 657, - "name": "build_pipes", - "arity": 2 - }, - "put/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "793ee208cdfb684424223eef5215d939c8bbaedfd9941bf4a46c75a7fdb94b61", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "put", - "arity": 3 - }, - "scope/4:1134": { - "line": 1134, - "guard": null, - "pattern": "path, alias, options, [do: context]", - "kind": "defmacro", - "end_line": 1144, - "ast_sha": "a078685fb8d216c1151cb1381db8b0513ebeb3e7eb2a8db4f69a8b72affb9ae8", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b3aeb41f56d10c83a9741400dc1eb8149b02f145546a2235161868316944e19e", - "start_line": 1134, - "name": "scope", - "arity": 4 - }, - "delete/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "96daae441d73ab81840590d74e2d8d764ebb1f6ee44d8cb31f0c90bf7459f27e", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "delete", - "arity": 3 - }, - "delete/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "c6989613a8d8fc6d604c07cefe03d6c0a7652849dfdb8ab39fe79eab3797d6c8", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "delete", - "arity": 4 - }, - "post/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "bb29c814b47c408571b7bf34756e385f0c1bf19f9255d0f07beead88807ff5bd", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "post", - "arity": 3 - }, - "plug/2:828": { - "line": 828, - "guard": null, - "pattern": "plug, opts", - "kind": "defmacro", - "end_line": 833, - "ast_sha": "932432518ae3fd6cbe76b3729fc1f3da26a56fb30221fca41072445142546d72", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "7d11be1b0c1cc1b5f3e9ca223db9a94d4448b0264ce945c5eaa50a38845842dc", - "start_line": 828, - "name": "plug", - "arity": 2 - }, - "put/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "771a9c5d991934aef109efde260b72158a6bc1b6d1faa34eb3dedfb7ed38309e", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "put", - "arity": 4 - }, - "add_resources/4:1021": { - "line": 1021, - "guard": null, - "pattern": "path, controller, options, [do: context]", - "kind": "defp", - "end_line": 1032, - "ast_sha": "17bfabd0cb71ebcf3beb99e755355bc76837d051be063630554628aced425859", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "a1978a19f713f08475b71fd30d67cc620d8230fdcc2299146bbd333e21c6f237", - "start_line": 1021, - "name": "add_resources", - "arity": 4 - }, - "route_info/4:1262": { - "line": 1262, - "guard": "is_binary(path)", - "pattern": "router, method, path, host", - "kind": "def", - "end_line": 1264, - "ast_sha": "6050107ba2e4ee748082220b0769a949c1c0dce7938e7b022457aee60107b1fe", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "741b5dade1d62f14dfd3dd2e08404483d7735eb2d6669050906a0dc8d4618886", - "start_line": 1262, - "name": "route_info", - "arity": 4 - }, - "trace/3:733": { - "line": 733, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "defmacro", - "end_line": 733, - "ast_sha": "456c0d1abd1c3e52172dc61c32975caaa24b00296b38400d1833c01acf6235a2", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "b31f0a59fab2fff3dc615ef8dd7fc361f54df1ce8a7cd3947f0e9fd3fa3c1260", - "start_line": 733, - "name": "trace", - "arity": 3 - }, - "verified_routes/0:473": { - "line": 473, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 473, - "ast_sha": "01a8c10409f41cf04c0e5e17278c1cdae122fe467851bbd79a30ed3ab02ad11d", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "ebfa1c9a879954efb1053fa49256efd4a0bc9e66c00088eafc5de0b0d1472957", - "start_line": 473, - "name": "verified_routes", - "arity": 0 - }, - "expand_plug_and_opts/3:840": { - "line": 840, - "guard": null, - "pattern": "plug, opts, caller", - "kind": "defp", - "end_line": 857, - "ast_sha": "224161e0d9cdeb5e03c50f38a93fc5f10147c1ddfae30b2c417f570b9d04fe60", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "f884150199adfbde9bb78fa43eb68bd2365cc9b2e8255c1bf2093a0aebb4f2c6", - "start_line": 840, - "name": "expand_plug_and_opts", - "arity": 3 - }, - "expand_alias/2:860": { - "line": 860, - "guard": null, - "pattern": "{:__aliases__, _, _} = alias, env", - "kind": "defp", - "end_line": 861, - "ast_sha": "46825d111bdb687c2946a41c5f062a2befb82c3f7b34afbd7463d35cc50a03b9", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "7599dd70b9a94c532aa4050ea2895b5b7ceb706318007c89ad50955b47a88598", - "start_line": 860, - "name": "expand_alias", - "arity": 2 - }, - "get/4:733": { - "line": 733, - "guard": null, - "pattern": "path, plug, plug_opts, options", - "kind": "defmacro", - "end_line": 734, - "ast_sha": "45216270138815a3ab2be8c3441d2bb94d614014221b153f8a90c9a42aa1064f", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "5140a377e6e9e93d7b6483fbc2bf7cbe26fd148f43e5f4d8321cb1f6839bf7df", - "start_line": 733, - "name": "get", - "arity": 4 - } - }, - "Phoenix.Presence": { - "__using__/1:367": { - "line": 367, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 368, - "ast_sha": "68967b139efedb77a4a6e280b8ea91befc6387a7c4109a564bd716057f91b011", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "f9c991da4efc6d6649e630a79d60f91ea5f8928cae07fc4c94e075c1466407ee", - "start_line": 367, - "name": "__using__", - "arity": 1 - }, - "add_new_presence_or_metas/4:676": { - "line": 676, - "guard": null, - "pattern": "topics, topic, key, new_metas", - "kind": "defp", - "end_line": 697, - "ast_sha": "67e24b010f5000165c9a546959901fa6fe9a77f4dab6dae603f6945b605bc4ed", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "858c280e0ac7dd54e1379471de3ecfb60d64403426dab9655157c7d0a7bfb46a", - "start_line": 676, - "name": "add_new_presence_or_metas", - "arity": 4 - }, - "add_new_topic/2:719": { - "line": 719, - "guard": null, - "pattern": "topics, topic", - "kind": "defp", - "end_line": 720, - "ast_sha": "e3d81a2226d4e9c619eadabdeb9a2f3c76f225d43b796324e4b5d83ba4bf5d0c", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "c7f5ccd5786fad8e008fe755d885230c618138bba90a2d757fc81e61b7cf628b", - "start_line": 719, - "name": "add_new_topic", - "arity": 2 - }, - "async_merge/2:620": { - "line": 620, - "guard": null, - "pattern": "state, diff", - "kind": "defp", - "end_line": 642, - "ast_sha": "d7f30286c81622d5ce5e05e4aae4c13d5677c6c4a19fcabcc4805dbcc2aa5631", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "ba2d407f79ea12a0e0383d79d5796c25ac79d4a296c02dfe5d75b8b963024880", - "start_line": 620, - "name": "async_merge", - "arity": 2 - }, - "do_handle_metas/2:596": { - "line": 596, - "guard": null, - "pattern": "state, computed_diffs", - "kind": "defp", - "end_line": 614, - "ast_sha": "727e59ea71dbddf424d5b274441ea3b4901f3bf0a6321bb6f0860f0c03289044", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "bc7edfca8dbe0cbb2b33d2bb1895a1d9907e667041e6c1a2c2c6c8f22fa48e6c", - "start_line": 596, - "name": "do_handle_metas", - "arity": 2 - }, - "get_by_key/3:558": { - "line": 558, - "guard": null, - "pattern": "module, topic, key", - "kind": "def", - "end_line": 568, - "ast_sha": "c1d62984e94150213c2227b1eb3b5d81e1dbc7a956d5f956b0e319355204ab0e", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "d7f2076ff9d9031e91e9a80b95da5e9f202378cbc35803fb8d0226412b590471", - "start_line": 558, - "name": "get_by_key", - "arity": 3 - }, - "group/1:573": { - "line": 573, - "guard": null, - "pattern": "presences", - "kind": "def", - "end_line": 578, - "ast_sha": "0af4b582f7ec7eb09b9f7423f181c0026cd817dc550c7e557bce76b707fd2908", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "74a6331ec89817d4d49cad983ce4bc08de7b8e8835386fa6191c4eba0da95356", - "start_line": 573, - "name": "group", - "arity": 1 - }, - "handle_diff/2:517": { - "line": 517, - "guard": null, - "pattern": "diff, state", - "kind": "def", - "end_line": 518, - "ast_sha": "6fc3a384b54fee2b155900f84774687638bfa879259d9d6b490902da3b20d439", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "9c2c5984b7aac245d62a769cb4f2a03079edf1e45b7667dc4b79102dc8a2d427", - "start_line": 517, - "name": "handle_diff", - "arity": 2 - }, - "handle_info/2:522": { - "line": 522, - "guard": null, - "pattern": "{task_ref, {:phoenix, ref, computed_diffs}}, state", - "kind": "def", - "end_line": 544, - "ast_sha": "2bcc7b4cb5a4479539b4b97ce1ac175205b61270b0142000560ae74166470398", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "b7a9d5ccc3b4ef044363dec2c5229cae0bd633ea56ba63d555cc64df901c90f0", - "start_line": 522, - "name": "handle_info", - "arity": 2 - }, - "handle_join/2:667": { - "line": 667, - "guard": null, - "pattern": "{joined_key, presence}, {topics, topic}", - "kind": "defp", - "end_line": 669, - "ast_sha": "18fdd7fb0f45fc3dc948bce0ffd272d299fc6e7e36943ded19bb0ddf22cd6cfb", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "439d2622e5ef301f087172a571319c0f7b0c50dc4703aac44e67caf2bd2c28bb", - "start_line": 667, - "name": "handle_join", - "arity": 2 - }, - "handle_leave/2:672": { - "line": 672, - "guard": null, - "pattern": "{left_key, presence}, {topics, topic}", - "kind": "defp", - "end_line": 673, - "ast_sha": "faf50a907ca6f44674ddae7ca53337ed57e9afed91efedcc44942cae12c1d557", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "09163f4b74e47036747219774a5d2da7b747113c098466de37d23e9fc03a1159", - "start_line": 672, - "name": "handle_leave", - "arity": 2 - }, - "init/1:475": { - "line": 475, - "guard": null, - "pattern": "{module, task_supervisor, pubsub_server, dispatcher}", - "kind": "def", - "end_line": 513, - "ast_sha": "dcce1b603ad2fa4c80edad6e9c9ff348e70132e611300ecaedb8ff4584acb7e1", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "b2f0301b8309f11558d76110b2fd085c8c8c4ddba8e4c815c02a8a7f6c2e8bef", - "start_line": 475, - "name": "init", - "arity": 1 - }, - "list/2:548": { - "line": 548, - "guard": null, - "pattern": "module, topic", - "kind": "def", - "end_line": 554, - "ast_sha": "bda1768f58d85f2b7ffd3722698d69acd9808b5b246bcdaaf7317272b79f2abf", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "42eda95dc58894a5da68ef7b5c22ddd61d8bde002fc8cbd6aa2405862a39afc0", - "start_line": 548, - "name": "list", - "arity": 2 - }, - "merge_diff/3:646": { - "line": 646, - "guard": null, - "pattern": "topics, topic, %{leaves: leaves, joins: joins} = _diff", - "kind": "defp", - "end_line": 663, - "ast_sha": "ccd1e2c9ee9d970670216e750bfdb2f18fc54711a6c158238c299bbb1a98e384", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "5b3d6e18c5c1f3f4b07e5efb1ec97d1f6e7a4ff005495d3003c8480d9054ee0f", - "start_line": 646, - "name": "merge_diff", - "arity": 3 - }, - "next_task/1:585": { - "line": 585, - "guard": null, - "pattern": "state", - "kind": "defp", - "end_line": 592, - "ast_sha": "e60d21c1a90cc17328c2389a21ed765ec60cbad6fb361cd4949342ea6bbd8bf0", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "5f84268267993b17d25b5d768bf5d70cf65fee33c3dd3ff762a55cdd255be6d9", - "start_line": 585, - "name": "next_task", - "arity": 1 - }, - "remove_presence_or_metas/4:700": { - "line": 700, - "guard": null, - "pattern": "topics, topic, key, deleted_metas", - "kind": "defp", - "end_line": 716, - "ast_sha": "3bcce89dc05e47afdf87c4b62019a9879cce233521bc793ece7fd7b6e3accba4", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "0a90d0dcaff699aff40eed24fe962f8210ab44d08c3eb9c1e196dc20c012c8cb", - "start_line": 700, - "name": "remove_presence_or_metas", - "arity": 4 - }, - "remove_topic/2:723": { - "line": 723, - "guard": null, - "pattern": "topics, topic", - "kind": "defp", - "end_line": 724, - "ast_sha": "af79d54349780ca8063a05a4770b03dc4ced380d9249a9262921865c174a0d28", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "ad4be2fa8d68ff72ee7de96679d1debcf479c96c1cd2a8691057ccf12b0a6987", - "start_line": 723, - "name": "remove_topic", - "arity": 2 - }, - "send_continue/2:583": { - "line": 583, - "guard": null, - "pattern": "%Task{} = task, ref", - "kind": "defp", - "end_line": 583, - "ast_sha": "db5713f74b8bb8c6248c7f306f8f023ddf80604f05a0a539eb5d338437c90065", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "b75eb1ed61d9fb337f9be329ddb8a916120784a314c57d06dddff14977939c45", - "start_line": 583, - "name": "send_continue", - "arity": 2 - }, - "start_link/3:453": { - "line": 453, - "guard": null, - "pattern": "module, task_supervisor, opts", - "kind": "def", - "end_line": 471, - "ast_sha": "18acd1bac5800499afa9b47e174a9d389e372799de751ed14577e77f8d61673c", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "6a298ad7b4a27f70d4dbbda1a102d5915d566d3d04e7cb5f3ff24df0da6a1432", - "start_line": 453, - "name": "start_link", - "arity": 3 - }, - "topic_presences_count/2:727": { - "line": 727, - "guard": null, - "pattern": "topics, topic", - "kind": "defp", - "end_line": 728, - "ast_sha": "da803893fbd700cc5e5d01634e81632fb2694c04c020d1531e93f56b33da564a", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "249170c84176285f6aadfdc6244009371202dec8b405c1d37ea3d76512f4c4cc", - "start_line": 727, - "name": "topic_presences_count", - "arity": 2 - } - }, - "Phoenix.Endpoint.RenderErrors": { - "__before_compile__/1:33": { - "line": 33, - "guard": null, - "pattern": "_", - "kind": "defmacro", - "end_line": 47, - "ast_sha": "82c6ae09d909d92c52a539a5a87de0f228c5423e7b0536bd3c821192ef4be6f4", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "108cf8ea564a291a46153998ebf300a5d7cee7784b3f78ae2136eb3f60c9a053", - "start_line": 33, - "name": "__before_compile__", - "arity": 1 - }, - "__catch__/5:54": { - "line": 54, - "guard": null, - "pattern": "%Plug.Conn{} = conn, kind, reason, stack, opts", - "kind": "def", - "end_line": 66, - "ast_sha": "d556beab6e43a7008010f41726c397ac13d411ee3efb4e31bf0b22a77dc28974", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "c72ad8b1048a21173da293ad43876cfba6515bede1410cce53f20672f7a3a938", - "start_line": 54, - "name": "__catch__", - "arity": 5 - }, - "__debugger_banner__/5:101": { - "line": 101, - "guard": null, - "pattern": "_conn, _status, _kind, %Phoenix.Router.NoRouteError{router: router}, _stack", - "kind": "def", - "end_line": 104, - "ast_sha": "712042a3d48fbe60ba34fd954770091d9b528342a95c4f1c10e4eacec2dd2193", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "8aaad5d82a4cb177e7335b0d7861a714294caba8576efe631adabddb204278ca", - "start_line": 101, - "name": "__debugger_banner__", - "arity": 5 - }, - "__debugger_banner__/5:108": { - "line": 108, - "guard": null, - "pattern": "_conn, _status, _kind, _reason, _stack", - "kind": "def", - "end_line": 108, - "ast_sha": "5c242f47cb826d0c976e1b24d1659469125944a91c9950ccc2674b1f93aa6654", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "eb78e7c81032ca52c12216ad3a888bdb7128b5217db70c3617968aa4b2da4a4d", - "start_line": 108, - "name": "__debugger_banner__", - "arity": 5 - }, - "__using__/1:25": { - "line": 25, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 28, - "ast_sha": "03d04ec64c48e45a3bf2942630bc6d452ce547d3d03b6507626fb72ac789f4f9", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "aae761bfe89bfbad3cee2da81048e90e3211c1600b1d50c1f320f01be879366c", - "start_line": 25, - "name": "__using__", - "arity": 1 - }, - "error_conn/3:92": { - "line": 92, - "guard": null, - "pattern": "_conn, :error, %Phoenix.Router.NoRouteError{conn: conn}", - "kind": "defp", - "end_line": 92, - "ast_sha": "faddf17b94fd077836bd425ea74ff7fa3f357b2f653981b7ccd1743addf09138", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "bc50bec290e264e2d1002872bc84f37f13a189b3b00b21822b643176e99c3c9e", - "start_line": 92, - "name": "error_conn", - "arity": 3 - }, - "error_conn/3:93": { - "line": 93, - "guard": null, - "pattern": "conn, _kind, _reason", - "kind": "defp", - "end_line": 93, - "ast_sha": "4749c1d4431d62aef0e3b862c06f851bc55595a27ff409ca815711956bfb5afd", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "b283ac64c7e3802d30f54b7f7ec72653479a17bac68121b9c2e65a4cfb062b8f", - "start_line": 93, - "name": "error_conn", - "arity": 3 - }, - "fetch_view_format/2:137": { - "line": 137, - "guard": null, - "pattern": "conn, opts", - "kind": "defp", - "end_line": 152, - "ast_sha": "62a217dc8fd729264ea1a91a4abe7b1256e79635d48c0271fd2603eb4c1a5aa6", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "c2311426aca2b904cbd27666cfae148f442b53caadc48f7cfdd8fd27d4f788d2", - "start_line": 137, - "name": "fetch_view_format", - "arity": 2 - }, - "instrument_render_and_send/5:69": { - "line": 69, - "guard": null, - "pattern": "conn, kind, reason, stack, opts", - "kind": "defp", - "end_line": 88, - "ast_sha": "a0e6e9bca6c453be181f14739f537cabdf247341f78b294152f423432744fe71", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "0ac4d5eb7e5671d7a5a96d8e276a52f0541c4a6bc9783466b6a7f0a8abe606bc", - "start_line": 69, - "name": "instrument_render_and_send", - "arity": 5 - }, - "maybe_fetch_query_params/1:127": { - "line": 127, - "guard": null, - "pattern": "%Plug.Conn{} = conn", - "kind": "defp", - "end_line": 133, - "ast_sha": "9a13af80b2f0bbb32febe2418d6215c809885505854f9461cc8e7d5bd739a268", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "33796c8e5551b5388cc66ad5627584514ef0365870b878c6831a32b5fe7ded65", - "start_line": 127, - "name": "maybe_fetch_query_params", - "arity": 1 - }, - "maybe_raise/3:95": { - "line": 95, - "guard": null, - "pattern": ":error, %Phoenix.Router.NoRouteError{}, _stack", - "kind": "defp", - "end_line": 95, - "ast_sha": "bca3ba06070c1f77b204d3097c862e2e4e2e8a5fb8772cfbc8650204b3b2dbe8", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "38abb91bc08609f0bada9357c6588646851f9f39613a87276545d0411b0ee7cc", - "start_line": 95, - "name": "maybe_raise", - "arity": 3 - }, - "maybe_raise/3:96": { - "line": 96, - "guard": null, - "pattern": "kind, reason, stack", - "kind": "defp", - "end_line": 96, - "ast_sha": "a0365a7f795aedfa980c39aa62ce9a51ce4f80201a20b268402642d15c8b39ca", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "8f978c6675c22d695969dd2040baeae15fa1310e547616aa369e31fd38415143", - "start_line": 96, - "name": "maybe_raise", - "arity": 3 - }, - "put_formats/2:156": { - "line": 156, - "guard": null, - "pattern": "conn, formats", - "kind": "defp", - "end_line": 188, - "ast_sha": "9cff9b410ccbabd0cff7c4a81fe20f573aaa4207e6c503ca1052415952dce11d", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "58f66d603cdbd95faafa972d2f3d7740736757e06dd71f0ab3cf7d797e0c2981", - "start_line": 156, - "name": "put_formats", - "arity": 2 - }, - "render/6:110": { - "line": 110, - "guard": null, - "pattern": "conn, status, kind, reason, stack, opts", - "kind": "defp", - "end_line": 124, - "ast_sha": "21a29a6b65abcd605cdc601d83959479fd2fc4f72374e70ea3a5f48913c27dad", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "9618fe666c4ec1d71bd1eb723eb1281e99398e218cb5feb0db95e125904f7e2b", - "start_line": 110, - "name": "render", - "arity": 6 - }, - "status/2:192": { - "line": 192, - "guard": null, - "pattern": ":error, error", - "kind": "defp", - "end_line": 192, - "ast_sha": "8b904952f554edbc193955ef2baf64a707854315787d221d86d9e75a0319374e", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "dd9db662eb5f46e31a4aff99d1fec71f8ab3a3cbbe70147da7f4dc0848d3c970", - "start_line": 192, - "name": "status", - "arity": 2 - }, - "status/2:193": { - "line": 193, - "guard": null, - "pattern": ":throw, _throw", - "kind": "defp", - "end_line": 193, - "ast_sha": "52b4c588afd73d6c190f97da20b381d0a890441731c3d4c41e5c523e93968d64", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "a7c99cd9a8218667a4608e938a8ff5bed3c651db5dd5224cc5895a80865ebfef", - "start_line": 193, - "name": "status", - "arity": 2 - }, - "status/2:194": { - "line": 194, - "guard": null, - "pattern": ":exit, _exit", - "kind": "defp", - "end_line": 194, - "ast_sha": "1274b943a7cbc8c46bccd0148de953a937513d8fc939bdf215dc52e05db8ae64", - "source_file": "lib/phoenix/endpoint/render_errors.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/render_errors.ex", - "source_sha": "4520cd93fdb485c3653c5a2afedcf1fcbb9a68f1c4bb0fcc684db0ae3bbf1a94", - "start_line": 194, - "name": "status", - "arity": 2 - } - }, - "Mix.Phoenix.Schema": { - "live_form_value/1:221": { - "line": 221, - "guard": null, - "pattern": "%Time{} = time", - "kind": "def", - "end_line": 221, - "ast_sha": "ef538e7121da66ab7540617e7f6ae917b5dd360842489dc13153ef08d7696384", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "b44c81b3eed4f21833692097c1b77c5aa8bf9563dce3ac0dca2ff46615cc1a1b", - "start_line": 221, - "name": "live_form_value", - "arity": 1 - }, - "maybe_redact_field/1:278": { - "line": 278, - "guard": null, - "pattern": "true", - "kind": "def", - "end_line": 278, - "ast_sha": "54870f06dd63c37caf53ea2492c4cbfed86cf6698d07c06c463cfe19fc2cd3e5", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ddcf1f8f791f983022ff6587d19e200e7d5bcecb85ffdfe19808dcbae717ebaf", - "start_line": 278, - "name": "maybe_redact_field", - "arity": 1 - }, - "build_enum_values/2:404": { - "line": 404, - "guard": null, - "pattern": "values, action", - "kind": "defp", - "end_line": 408, - "ast_sha": "9e0d4fce96831153e7acb724212d79d7f2d9428537ce6526e91a2ee0cdb0580e", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "d24d70f98ae5fb6d183698f9ba2c41d626d18d76edd7f4f6cb67a90769ac42c0", - "start_line": 404, - "name": "build_enum_values", - "arity": 2 - }, - "build_array_values/2:398": { - "line": 398, - "guard": null, - "pattern": ":integer, :update", - "kind": "defp", - "end_line": 398, - "ast_sha": "e6363b4a5d163caa2580100778b7812b04bb3ba223d31ec564df70eb9d52664e", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "47b98410d0580dd630840f6f9c8bb85c0dbe6e9295f7426a08b16fdb407f7c9f", - "start_line": 398, - "name": "build_array_values", - "arity": 2 - }, - "build_utc_datetime_usec/0:412": { - "line": 412, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 413, - "ast_sha": "7d08059f69173f08ddf46000f54aef651d3ff2046641d219be58ae6b7cf3fbd1", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "8c0882fda11ecefe43fcb2a59d6d4316f8ed8828e4cc852fe9cb1c4f2fe9ef02", - "start_line": 412, - "name": "build_utc_datetime_usec", - "arity": 0 - }, - "partition_attrs_and_assocs/3:453": { - "line": 453, - "guard": null, - "pattern": "schema_module, attrs, scope", - "kind": "defp", - "end_line": 481, - "ast_sha": "9647394e096df223aafb9b74695d7f5758d41e21ff8c47bcb51c2889de74adda", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ee9f68904f27acf1e1587a77bb0b7c5b5f9090bef96992333259feb60c50e05f", - "start_line": 453, - "name": "partition_attrs_and_assocs", - "arity": 3 - }, - "maybe_redact_field/1:279": { - "line": 279, - "guard": null, - "pattern": "false", - "kind": "def", - "end_line": 279, - "ast_sha": "000d291874dae900a9be63ced128afd096b73fa58f9741f5acbfb347943a59dc", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "4c3dcbb08f7e227a9591f9f6726a906f2df4cde25e1c3197503a1b1a583accdd", - "start_line": 279, - "name": "maybe_redact_field", - "arity": 1 - }, - "fixture_unique_functions/3:580": { - "line": 580, - "guard": null, - "pattern": "singular, uniques, attrs", - "kind": "defp", - "end_line": 615, - "ast_sha": "d77752e611c7fa7f28cdff9e937076e3ecf431db7e188562a5c445b5520af8e7", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "5793ad5d76d15b8e52a779f92b9b01ffb940dece8d569d382c020734252f51a4", - "start_line": 580, - "name": "fixture_unique_functions", - "arity": 3 - }, - "list_to_attr/1:296": { - "line": 296, - "guard": null, - "pattern": "[key, comp, value]", - "kind": "defp", - "end_line": 297, - "ast_sha": "bf2eb4b83019ed5e920c853d7cee16e41fb1fcdb98fa35676b437efe4cb9d93c", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "5bc38da584c77c2c80d25f39ade781090a126d36d75b95d3a074ecff855d3999", - "start_line": 296, - "name": "list_to_attr", - "arity": 1 - }, - "validate_scope_and_reference_conflict!/2:484": { - "line": 484, - "guard": null, - "pattern": "%Mix.Phoenix.Scope{schema_key: reference_key}, reference_key", - "kind": "defp", - "end_line": 489, - "ast_sha": "15cc8c5b531676a0f2552ba85100294c6574aa21c94b3ed3f57046506f811c59", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "b02b3c82405ad462760c0f7aa1a14023ef126189f1bcdf11a023c42a041dc6b8", - "start_line": 484, - "name": "validate_scope_and_reference_conflict!", - "arity": 2 - }, - "type_to_default/3:367": { - "line": 367, - "guard": null, - "pattern": "key, t, :update", - "kind": "defp", - "end_line": 385, - "ast_sha": "7944c7c01318ab9a5c6f5ec1d6005d8a163687edb32d3aa6b10571204efc83e7", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "593b5159a2a3d1c2989a2fe084891639c25eb213ff8076dc84799900c6d653f4", - "start_line": 367, - "name": "type_to_default", - "arity": 3 - }, - "params/2:209": { - "line": 209, - "guard": "=:=(action, :create) or =:=(action, :update)", - "pattern": "attrs, action", - "kind": "def", - "end_line": 210, - "ast_sha": "90e71646e8f137f9af7b82baad2b545fb674b5d3487d73246ceb8f617da04782", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "78d4de099efca017b6b2bce315890a3fb2ab64e8f3b9d51730e333e1175b561f", - "start_line": 209, - "name": "params", - "arity": 2 - }, - "type_for_migration/1:256": { - "line": 256, - "guard": null, - "pattern": "{:enum, _}", - "kind": "def", - "end_line": 256, - "ast_sha": "462756be699666ecf17e71bcd40bdbd2a4f5401be722f4d79846ef00183ec9bd", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "9f79fabbdf26a0cb5b53c84a0f94e0815002130bb603f91b67c25c020174426d", - "start_line": 256, - "name": "type_for_migration", - "arity": 1 - }, - "list_to_attr/1:294": { - "line": 294, - "guard": null, - "pattern": "[key, value]", - "kind": "defp", - "end_line": 294, - "ast_sha": "a4b07491dccbdf8972dadf4d2934e9fb1cd435352e96ccf510dce6aa491f22fe", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "62c51055e549562a0bc88ccd0e3e89ddbbbd5fceb964d30148f3a61d9f674fac", - "start_line": 294, - "name": "list_to_attr", - "arity": 1 - }, - "migration_module/0:573": { - "line": 573, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 576, - "ast_sha": "381265538d03f9f8feba307572e7d8dacf1c43a69acb07a8ba8844d2c0418120", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "8d414873f81da75065ee0c715daab12655cc6a39010b330a3d682b0c52b98831", - "start_line": 573, - "name": "migration_module", - "arity": 0 - }, - "type_and_opts_for_schema/1:273": { - "line": 273, - "guard": null, - "pattern": "{:enum, opts}", - "kind": "def", - "end_line": 274, - "ast_sha": "50df40637caae958cc247f1b0c26bd2aaf679905c8730934776bbe7c6186c543", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "29385e3ba7b39c8612042d062cb125183acd97d242f65c6dc8905220bd374ddc", - "start_line": 273, - "name": "type_and_opts_for_schema", - "arity": 1 - }, - "build_array_values/2:401": { - "line": 401, - "guard": null, - "pattern": "_, _", - "kind": "defp", - "end_line": 401, - "ast_sha": "b535731167206a53b9c17a959c5243c11babb12052fad89f66b6d524d7c657a7", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "853769d0266179c6b0ea316c8c725610da47abab56170e4389590fa11525fd86", - "start_line": 401, - "name": "build_array_values", - "arity": 2 - }, - "route_helper/2:562": { - "line": 562, - "guard": null, - "pattern": "web_path, singular", - "kind": "defp", - "end_line": 565, - "ast_sha": "6cc400a82155a75348293d0865ecfa9264b343bbcdd4dc5123ccb786ed05599a", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "538371183c75873f695d06e9ac3ae305cd9cd7ceb6c489e390637ed661b0c54d", - "start_line": 562, - "name": "route_helper", - "arity": 2 - }, - "valid_types/0:69": { - "line": 69, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 69, - "ast_sha": "e0f7990f452bbee24b7928c176eb46c5fb3d22f7a1575e29ca2621466505412f", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "1d983e6cea12a035775e82ac70ea5474f3e5a8eb7deca96e24ffbb3e3f300144", - "start_line": 69, - "name": "valid_types", - "arity": 0 - }, - "type_and_opts_for_schema/1:276": { - "line": 276, - "guard": null, - "pattern": "other", - "kind": "def", - "end_line": 276, - "ast_sha": "f50e8cf37b0e2cc41465dfa8c9656e03f1394dece7abd25731e36093fecef5c0", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "c2ec5e7ac303f713291ac23f9d48cf1cf7fff1fc03cb2314ac90d19b4af58c96", - "start_line": 276, - "name": "type_and_opts_for_schema", - "arity": 1 - }, - "validate_attr!/1:443": { - "line": 443, - "guard": "=:=(type, :integer) or =:=(type, :float) or =:=(type, :decimal) or =:=(type, :boolean) or\n =:=(type, :map) or =:=(type, :string) or =:=(type, :array) or =:=(type, :references) or\n =:=(type, :text) or =:=(type, :date) or =:=(type, :time) or =:=(type, :time_usec) or\n =:=(type, :naive_datetime) or =:=(type, :naive_datetime_usec) or =:=(type, :utc_datetime) or\n =:=(type, :utc_datetime_usec) or =:=(type, :uuid) or =:=(type, :binary) or =:=(type, :enum)", - "pattern": "{_name, type} = attr", - "kind": "defp", - "end_line": 443, - "ast_sha": "610ddd864a575d5b0d3f0881888ce71b0e7bd0728dc4d541f43db88831ead2fa", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "e6bed7fe2837eef09242a4363babfb514255bb96a83a808869b5683ed46fab9a", - "start_line": 443, - "name": "validate_attr!", - "arity": 1 - }, - "__struct__/1:6": { - "line": 6, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 6, - "ast_sha": "adff79d2c708b4c68abfa00c4ba78ecb1b8b4921e6b7a40620b0b9840b23e2af", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "d2cd594a48ad511cc35d57efe9641417e24ea647197f26f1c4ae61b6400bf0a6", - "start_line": 6, - "name": "__struct__", - "arity": 1 - }, - "indexes/3:535": { - "line": 535, - "guard": null, - "pattern": "table, assocs, uniques", - "kind": "defp", - "end_line": 543, - "ast_sha": "d4a632e43ac965d56952cc5c124e847bc0c6ee9979dbd60a9327544d20111c8b", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "27a8dc8bdbe2da5f7e4f7feb4632ecd6f34dcf061ac30fc6ae79e3c75c7f2c13", - "start_line": 535, - "name": "indexes", - "arity": 3 - }, - "type_for_migration/1:257": { - "line": 257, - "guard": null, - "pattern": "other", - "kind": "def", - "end_line": 257, - "ast_sha": "c4b4f23c539c1ed55fcb99ec159aaa9b9c0c0c60b13304928c8d8edd86515374", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "5a2f9b57fce3fb2fdb6e175409fa9a8768c6f45837b303a8afcad6af7121c273", - "start_line": 257, - "name": "type_for_migration", - "arity": 1 - }, - "list_to_attr/1:293": { - "line": 293, - "guard": null, - "pattern": "[key]", - "kind": "defp", - "end_line": 293, - "ast_sha": "0ad3fbc70511dae36638ab5feebc9c09166e6fd10b67ccd611029717a1455373", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "bed72be1096c060784b46b63af252a6d33e5e11c589f34749d20b7f8f9ccec34", - "start_line": 293, - "name": "list_to_attr", - "arity": 1 - }, - "extract_attr_flags/1:174": { - "line": 174, - "guard": null, - "pattern": "cli_attrs", - "kind": "def", - "end_line": 182, - "ast_sha": "db50078f1ce357ffb224353bc0e26c39c778267725c1ef503b568c5949241ff2", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "cb1afe1891f03224319f969c647cd4fc930193ced744c64f8ebbb84c99d4abcc", - "start_line": 174, - "name": "extract_attr_flags", - "arity": 1 - }, - "inspect_value/2:291": { - "line": 291, - "guard": null, - "pattern": "_type, value", - "kind": "defp", - "end_line": 291, - "ast_sha": "12e309937a294602e94fb940dc70e135f2769643dc80033b3758e07323ce8554", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "0d17ff7e2a6f905337e2631503e4c2802aca549b075e06a27ba6c78e8d7a7d8e", - "start_line": 291, - "name": "inspect_value", - "arity": 2 - }, - "build_array_values/2:389": { - "line": 389, - "guard": null, - "pattern": ":string, :create", - "kind": "defp", - "end_line": 390, - "ast_sha": "d1a6759c19f5628d18c2f081f3904fc594883e0bd3091d89292cac15885c2fe7", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "8869ece9023f4a2dcad454fb444e9ca2330ed529a7f21b40d021f3c483d2ec42", - "start_line": 389, - "name": "build_array_values", - "arity": 2 - }, - "types/1:509": { - "line": 509, - "guard": null, - "pattern": "attrs", - "kind": "defp", - "end_line": 513, - "ast_sha": "f22d61bc9536383c3fe65166cd72bed3f2166e0eb1e7b58ce0e658a0e8a8e529", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "a8a39ebb7316c0ad47bcc1fe3f985aea1065c0a83a88198ee73b5bca484c74c4", - "start_line": 509, - "name": "types", - "arity": 1 - }, - "invalid_form_value/1:240": { - "line": 240, - "guard": "is_list(value)", - "pattern": "value", - "kind": "def", - "end_line": 240, - "ast_sha": "5761b9d3c40e935d9785f8b8d65755ba4f3b92c72205c243b52ba28e3d50e4e1", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "2aeee5f8c8a9e379eb0a0f30033f0ee5b9b2a87af1b4e5c3efd7194c35d291f9", - "start_line": 240, - "name": "invalid_form_value", - "arity": 1 - }, - "build_utc_naive_datetime/0:421": { - "line": 421, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 422, - "ast_sha": "fae2f99c9bb071e2bb97fb10ee6b3876c45e37bb887257d587d89a1003501428", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "078959c85e54f4daec7fb43aee992eedbbabd7cf57737395d35b016942b36d3f", - "start_line": 421, - "name": "build_utc_naive_datetime", - "arity": 0 - }, - "invalid_form_value/1:247": { - "line": 247, - "guard": null, - "pattern": "_value", - "kind": "def", - "end_line": 247, - "ast_sha": "634349d9494dffcf415d3e0328fa0a36e6434ed2d40946019e4b62991518f942", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "6fc8d628abd4c6795f8953cc733f179896eaa4e636ab25753725374afb01544a", - "start_line": 247, - "name": "invalid_form_value", - "arity": 1 - }, - "split_flags/5:188": { - "line": 188, - "guard": null, - "pattern": "[\"redact\" | rest], name, attrs, uniques, redacts", - "kind": "defp", - "end_line": 189, - "ast_sha": "e0bcb0ffd93ed34d3c1723d62e7d51191624a9610df10dcee7800af12aa80362", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "11dd31c7ba9a7fcbe09d06a6c571fe528db8b4436cac4ce48a753fa8a5cae221", - "start_line": 188, - "name": "split_flags", - "arity": 5 - }, - "schema_defaults/1:495": { - "line": 495, - "guard": null, - "pattern": "attrs", - "kind": "defp", - "end_line": 498, - "ast_sha": "396fd860a8dc3878ce137032bc164994f9c59892283a8d933af24da6883cd4fe", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f86a36e8f72a1c852fe222e3ef8b056b466d2c9d5e2363a4e10be9dcd023e31a", - "start_line": 495, - "name": "schema_defaults", - "arity": 1 - }, - "invalid_form_value/1:242": { - "line": 242, - "guard": null, - "pattern": "%{day: _day, month: _month, year: _year} = _date", - "kind": "def", - "end_line": 242, - "ast_sha": "ebb85777a0847ff608e32b2ffbc592901dfa1bae3aa6d26ab90f883aa77d51fe", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "e14c396654f1e6f65a0ec44e95323a2526990c164d498e899fda04192e68f800", - "start_line": 242, - "name": "invalid_form_value", - "arity": 1 - }, - "inspect_value/2:290": { - "line": 290, - "guard": null, - "pattern": ":decimal, value", - "kind": "defp", - "end_line": 290, - "ast_sha": "36de7841eef5264c2a489e05bd2d68d1509c7724fe947c343168c518270185a7", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "c0ba4fcd57abf3b2e3bebccb7a15bdaa82a4327ae10d2d091938d4f94d389e74", - "start_line": 290, - "name": "inspect_value", - "arity": 2 - }, - "format_fields_for_schema/1:259": { - "line": 259, - "guard": null, - "pattern": "schema", - "kind": "def", - "end_line": 261, - "ast_sha": "ff86a67f617df8300c555e1584f1478289a16bff8913857b3560a48e6d37ebb8", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "9ca2f63de0ec6593e89441f0d63300f5b29cb2f9f9e610adbe0ff63a602e120c", - "start_line": 259, - "name": "format_fields_for_schema", - "arity": 1 - }, - "split_flags/5:185": { - "line": 185, - "guard": null, - "pattern": "[\"unique\" | rest], name, attrs, uniques, redacts", - "kind": "defp", - "end_line": 186, - "ast_sha": "64e11ec1aac721ef4d861919618286614b504486b684ccefbca77c8faee5faed", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "2e8480e64c50f46f9b40431d4b8c59e8d4f2ff82c97a716734d68b1992bb49b6", - "start_line": 185, - "name": "split_flags", - "arity": 5 - }, - "default_param/2:167": { - "line": 167, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema, action", - "kind": "def", - "end_line": 171, - "ast_sha": "bd6d821ba884d812b9407ec73aa67b928eefb8ea3aed97b7303b72f6f60392b0", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "9bdb068f4b8dcad88bc8dd88f0d0670fc177d83e3b57f35f759e1744510e2ac7", - "start_line": 167, - "name": "default_param", - "arity": 2 - }, - "live_form_value/1:219": { - "line": 219, - "guard": null, - "pattern": "%Date{} = date", - "kind": "def", - "end_line": 219, - "ast_sha": "01cc67489f241f7a3f7e49f4b7e4d7d30255b3af395a5c4464d9050ede0a3cbd", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ed004aeb270d9641a896969965c50e4083192376f629ab5296c381c3059ed8dc", - "start_line": 219, - "name": "live_form_value", - "arity": 1 - }, - "validate_attr!/1:446": { - "line": 446, - "guard": null, - "pattern": "{_, type}", - "kind": "defp", - "end_line": 449, - "ast_sha": "f9cca53eea1e58d2040cfbd1ce5672e7c4fb76b5ea18c8b133414f1bf2e00a9f", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "a8cfc19e79201ac16f1b2bcfb03e31c4b81fbeea2bcdb3401ffd8b71b0dfd197", - "start_line": 446, - "name": "validate_attr!", - "arity": 1 - }, - "schema_type/1:527": { - "line": 527, - "guard": null, - "pattern": "val", - "kind": "defp", - "end_line": 531, - "ast_sha": "8602be6b10bafc5846401847978b0f39e2a9f45fe0af38608f7eb0c62f832e42", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "7965e824f612530eaf76dd638246315a7878275e9460011e5e829d1430691be0", - "start_line": 527, - "name": "schema_type", - "arity": 1 - }, - "type_to_default/3:302": { - "line": 302, - "guard": null, - "pattern": "key, t, :create", - "kind": "defp", - "end_line": 363, - "ast_sha": "38f7a1f08ddabe56e06e62edb0270be911c71f6d3385082c5764d2e55e743a63", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f06365b3b0cfaff3815ac5e2a08eb9922c745b5b4f19185c7b9d25a6e4af7c56", - "start_line": 302, - "name": "type_to_default", - "arity": 3 - }, - "build_array_values/2:392": { - "line": 392, - "guard": null, - "pattern": ":integer, :create", - "kind": "defp", - "end_line": 392, - "ast_sha": "3c25924e53530ac1a7f76a764e7e74baf469b5309197210a00f6574bec2d7323", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "0666118eb18734edd0e3b7d4a22034caec8489ab94abaa9c19545efa232b0bee", - "start_line": 392, - "name": "build_array_values", - "arity": 2 - }, - "build_utc_datetime/0:415": { - "line": 415, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 416, - "ast_sha": "1e420ba105637d02affe391a4e68d5e724a489d4ac5505eb4ee543c40bad23a8", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "3c0557b24102edcae647327cb80ae134a31fdcb21060d1eea8cca3fd9564a05f", - "start_line": 415, - "name": "build_utc_datetime", - "arity": 0 - }, - "value/3:284": { - "line": 284, - "guard": null, - "pattern": "schema, field, value", - "kind": "def", - "end_line": 287, - "ast_sha": "90de58bccc18df4b2c60b0be20a7dc221f9efab9765715dec25439d9909b5d64", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "2c215426fffc891c379fbe20cecab225145af0fd45bdcf4f7d19b91903fc89f8", - "start_line": 284, - "name": "value", - "arity": 3 - }, - "params/1:209": { - "line": 209, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 209, - "ast_sha": "1ed77c9d852b04303003a09cf35fe3ce3a0dfbdb482fe6b69c1f1420e19ad097", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "350397c7684734c772a7d78f81ce4969ca07e2281294eb325d988cee155dfe4c", - "start_line": 209, - "name": "params", - "arity": 1 - }, - "new/4:75": { - "line": 75, - "guard": null, - "pattern": "schema_name, schema_plural, cli_attrs, opts", - "kind": "def", - "end_line": 160, - "ast_sha": "941841b24f713aa730487b659f607b1fb2f157e0554874c24ba4153de978526a", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "c16936e6b625a24acad3cefbbf9c83d1a78e13428f337115103e402b820d3732", - "start_line": 75, - "name": "new", - "arity": 4 - }, - "fixture_params/2:619": { - "line": 619, - "guard": null, - "pattern": "attrs, fixture_unique_functions", - "kind": "defp", - "end_line": 628, - "ast_sha": "3a11264ce911aaa91b5ba6263c890e9bb3d3a68bb6c3b28d4a0bce4cc224f02a", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "a603037b49c2de03f8a536ca462f8f66b1061968c299c404bc7236e6241fdbaf", - "start_line": 619, - "name": "fixture_params", - "arity": 2 - }, - "required_fields/1:269": { - "line": 269, - "guard": null, - "pattern": "schema", - "kind": "def", - "end_line": 270, - "ast_sha": "f3eddcf0aae25947fddbe2777d984feac53466028ae01167b5c2a9ba9e745b1b", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "cfa687658fad46ce8bf44d920183b5b6565496a1f15a62ef8f87c464c171401d", - "start_line": 269, - "name": "required_fields", - "arity": 1 - }, - "live_form_value/1:227": { - "line": 227, - "guard": null, - "pattern": "%DateTime{} = naive", - "kind": "def", - "end_line": 228, - "ast_sha": "2028d03554099af8379b1f305b209290e951b96fcbf2187ed8edbe2f57b9df58", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "1f888cec8ce978df0292187cc0cd8143451a33f61bcf7eeacac499ba925cfa20", - "start_line": 227, - "name": "live_form_value", - "arity": 1 - }, - "__struct__/0:6": { - "line": 6, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 6, - "ast_sha": "e306b77ceb58c149d9cb03cbe70af8916e9adc98b8aaa4e0c98d441e58ad20a1", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "d2cd594a48ad511cc35d57efe9641417e24ea647197f26f1c4ae61b6400bf0a6", - "start_line": 6, - "name": "__struct__", - "arity": 0 - }, - "schema_type/1:525": { - "line": 525, - "guard": null, - "pattern": ":uuid", - "kind": "defp", - "end_line": 525, - "ast_sha": "f0d8ff6cd9cbe32eebec9b5ffd82936524f91b3c2c5293de14fb0032cb89ec79", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "52c6680c40b9dbe8b1c964fa0a564cbc46861028cff1b75ef4b2b2729e9bbf46", - "start_line": 525, - "name": "schema_type", - "arity": 1 - }, - "live_form_value/1:231": { - "line": 231, - "guard": null, - "pattern": "value", - "kind": "def", - "end_line": 231, - "ast_sha": "49ddea2d3a43e2fd798386394567ead0e1fe27bedded580f2537b308c7901e59", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "80a900aa415424c1aa12abdc6287fba4bc6124231685c133facf5286456f3cf2", - "start_line": 231, - "name": "live_form_value", - "arity": 1 - }, - "attrs/1:197": { - "line": 197, - "guard": null, - "pattern": "attrs", - "kind": "def", - "end_line": 202, - "ast_sha": "ce0ac0b134e77b3b47a1cff618afa76860e72f44fc46408b3c4575d3a35f1d4e", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ea744d6fa585289e0d85282f71bf5ee92ab19f0067f1847dafb7ec6e66e485ba", - "start_line": 197, - "name": "attrs", - "arity": 1 - }, - "string_attr/1:502": { - "line": 502, - "guard": null, - "pattern": "types", - "kind": "defp", - "end_line": 505, - "ast_sha": "50aba7bbd709d97d7ad2423751ab2b98193e84322ff05f726363ef1891775569", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "3051083a52a2c33601c3664da27f9b659caeb44c60d60884e3f16879fbc8d009", - "start_line": 502, - "name": "string_attr", - "arity": 1 - }, - "schema_type/1:524": { - "line": 524, - "guard": null, - "pattern": ":text", - "kind": "defp", - "end_line": 524, - "ast_sha": "fb499b23292b1f2577fa0fff47d4b1666bbd3e46fbc61601f57cb3859c813d79", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "46225aef5557ef1b905ae9f7485e9c70e6b44d134e30082adaea88d45693d766", - "start_line": 524, - "name": "schema_type", - "arity": 1 - }, - "migration_defaults/1:547": { - "line": 547, - "guard": null, - "pattern": "attrs", - "kind": "defp", - "end_line": 550, - "ast_sha": "a58bf9538f7c444c24b22180021812d016656d8ab4a16ade026cdbddfc5e5079", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f88451621150ebae69586d57f70e8328bcd8816717689c796fe5db1b9d1db708", - "start_line": 547, - "name": "migration_defaults", - "arity": 1 - }, - "valid?/1:71": { - "line": 71, - "guard": null, - "pattern": "schema", - "kind": "def", - "end_line": 72, - "ast_sha": "9e1affdfbd037feb6b3a6802b0ada912c3572184071e644bcb254daa2b0f8b15", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "4d6e7aab6858bd3a253a960903f4c76acdef86a48ea79165f1dee77e0dbe3931", - "start_line": 71, - "name": "valid?", - "arity": 1 - }, - "failed_render_change_message/1:252": { - "line": 252, - "guard": null, - "pattern": "_schema", - "kind": "def", - "end_line": 252, - "ast_sha": "b5bbb1a4ba62a70f2019d233906472be53875f77ffc506d290a41499aa01e2c6", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "af590b0bad262f1e70b6ebe1a7ea0a617a5e7ad5306a76c2d1bfe5b56f7be1cf", - "start_line": 252, - "name": "failed_render_change_message", - "arity": 1 - }, - "validate_attr!/1:433": { - "line": 433, - "guard": null, - "pattern": "{name, :array}", - "kind": "defp", - "end_line": 435, - "ast_sha": "27ac89f0e13e777097b5bed75000641eceef3ee0ba39ec01a80032b57b0c3ef2", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "e56503ec04214aa965df69790720b25cda38aeb5da4ab86f12a0bf68e2152cb8", - "start_line": 433, - "name": "validate_attr!", - "arity": 1 - }, - "validate_attr!/1:444": { - "line": 444, - "guard": "=:=(type, :integer) or =:=(type, :float) or =:=(type, :decimal) or =:=(type, :boolean) or\n =:=(type, :map) or =:=(type, :string) or =:=(type, :array) or =:=(type, :references) or\n =:=(type, :text) or =:=(type, :date) or =:=(type, :time) or =:=(type, :time_usec) or\n =:=(type, :naive_datetime) or =:=(type, :naive_datetime_usec) or =:=(type, :utc_datetime) or\n =:=(type, :utc_datetime_usec) or =:=(type, :uuid) or =:=(type, :binary) or =:=(type, :enum)", - "pattern": "{_name, {type, _}} = attr", - "kind": "defp", - "end_line": 444, - "ast_sha": "95459accde92b128e6ab9d7fa2f8a0274227213b2641dab80b8c771ef529b19b", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "b474dad803a91f0434d4fadc65856447d6af1cdc9f25f80a25675eed29318d12", - "start_line": 444, - "name": "validate_attr!", - "arity": 1 - }, - "sample_id/1:554": { - "line": 554, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 556, - "ast_sha": "5cb59bfec6c9163766a4abfdaea00a1dc7ba55d6689bc8d0cffbb98aa9e372db", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ed65b909c585cf6cf926a1fcf99f2bff3ac51d2a5d677a775baa2483f8a757f7", - "start_line": 554, - "name": "sample_id", - "arity": 1 - }, - "build_utc_naive_datetime_usec/0:418": { - "line": 418, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 419, - "ast_sha": "da945f787ebd2ccc40e90ec37b6db2c8278a8a6e847310a60e4dae617d3f1a24", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "bd8956dbb377a027fc687b53b8e97bad4e5a3352bef68086d3eeaeb2095dfd3e", - "start_line": 418, - "name": "build_utc_naive_datetime_usec", - "arity": 0 - }, - "validate_scope_and_reference_conflict!/2:493": { - "line": 493, - "guard": null, - "pattern": "_scope, _source", - "kind": "defp", - "end_line": 493, - "ast_sha": "70075dd5964b0bdeeecc8ab6d8232362a1d4c5236b141b1524e7d23a6ec5ddfe", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f1d6ec06de22d8e9b48993900ba8a0bec43aa58dbb69ae3ed670f6a1484dd5a3", - "start_line": 493, - "name": "validate_scope_and_reference_conflict!", - "arity": 2 - }, - "translate_enum_vals/1:517": { - "line": 517, - "guard": null, - "pattern": "vals", - "kind": "def", - "end_line": 521, - "ast_sha": "9588a831ccf6eb119828615a7f92ced1330d7160766f3703d16da9c9efcdc918", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "2e149a358cbe73d4166b53e4502e7a3614b688f1a67d67ba37833099cf393867", - "start_line": 517, - "name": "translate_enum_vals", - "arity": 1 - }, - "invalid_form_value/1:246": { - "line": 246, - "guard": null, - "pattern": "true", - "kind": "def", - "end_line": 246, - "ast_sha": "955067d85247ecc95bdfe88d397307d8c9d02f06e4e8daa27c7a843f06f18bd1", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "07018e65ec43e97fa20635b2f0c3f11c9ca8f2cfb0ea1e9924533983d0eb54a4", - "start_line": 246, - "name": "invalid_form_value", - "arity": 1 - }, - "build_array_values/2:395": { - "line": 395, - "guard": null, - "pattern": ":string, :update", - "kind": "defp", - "end_line": 395, - "ast_sha": "15f679594b16db733c4cce6413d1519a217e6c59eaf9ca73fe329a3872bdf28c", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f093876506f164d24bda31dbe207408f417465e7112d252371ba325863edc248", - "start_line": 395, - "name": "build_array_values", - "arity": 2 - }, - "split_flags/5:191": { - "line": 191, - "guard": null, - "pattern": "rest, name, attrs, uniques, redacts", - "kind": "defp", - "end_line": 192, - "ast_sha": "696955d69718bcae2a52bd94838a8222a3eaba88634fc90a0fbf5dd909d07e0d", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "ed49e58df778d30bb8ca998b1674bb079acb84a2ac2591e16e4450c729e22226", - "start_line": 191, - "name": "split_flags", - "arity": 5 - }, - "route_prefix/2:568": { - "line": 568, - "guard": null, - "pattern": "web_path, plural", - "kind": "defp", - "end_line": 570, - "ast_sha": "872b66d1894f1c64fbe006fa5ec82531069454cf7bd6db5d068c297e732c2887", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "f0312b7a532e60f46683237ab4261fc7b819b5dcbd3b4229a50f800e276b1e38", - "start_line": 568, - "name": "route_prefix", - "arity": 2 - }, - "validate_attr!/1:442": { - "line": 442, - "guard": null, - "pattern": "{_name, :enum}", - "kind": "defp", - "end_line": 442, - "ast_sha": "880f2952c69682c74b432b3ce74b4514959a85e43eae3d979e5d26672ff19d18", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "e6cb5a1a2a0f9df408d065a021a12d724e7c74843499c943e09e7ab8e660919d", - "start_line": 442, - "name": "validate_attr!", - "arity": 1 - }, - "invalid_form_value/1:245": { - "line": 245, - "guard": null, - "pattern": "%{hour: _hour, minute: _minute}", - "kind": "def", - "end_line": 245, - "ast_sha": "90fcd2ee04bba220e1c2abec7aa1b96636a51ecae365ed8385ffee04da20a53f", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "44cfe2dbfe276cdc86af61e4227553632424ad183c82bad1741bcfd69b667695", - "start_line": 245, - "name": "invalid_form_value", - "arity": 1 - }, - "validate_attr!/1:431": { - "line": 431, - "guard": null, - "pattern": "{name, :datetime}", - "kind": "defp", - "end_line": 431, - "ast_sha": "fca785ec6c439454787568c7dd7d7d05f1257f67f8c1d199603c7dc4184a5bdc", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "80bdc348908e63601bb5ee3abc57c05e3902c3ce9f3bc95d836844734e6dbdf0", - "start_line": 431, - "name": "validate_attr!", - "arity": 1 - }, - "live_form_value/1:223": { - "line": 223, - "guard": null, - "pattern": "%NaiveDateTime{} = naive", - "kind": "def", - "end_line": 224, - "ast_sha": "f9468d30ebc9cde309cc2fffa6d043ad6c9a53b740204ba0f25c163173aa31ed", - "source_file": "lib/mix/phoenix/schema.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/schema.ex", - "source_sha": "9067c2764cbcaf2cbcb76456747fb464e8f2f3d0bc75f70abcaa42bcc9db2895", - "start_line": 223, - "name": "live_form_value", - "arity": 1 - } - }, - "Phoenix.Debug": { - "channel_process?/1:86": { - "line": 86, - "guard": null, - "pattern": "pid", - "kind": "def", - "end_line": 94, - "ast_sha": "fb891be6011ad4769005bee70f75c9bba8d9426be0d467179dbaa8504efa93e2", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "14c7841dbd2231a5cd434bc4302b71b7c08936efa8a2b93948ce5de5dc11a3fb", - "start_line": 86, - "name": "channel_process?", - "arity": 1 - }, - "keyfind/2:44": { - "line": 44, - "guard": null, - "pattern": "list, key", - "kind": "defp", - "end_line": 47, - "ast_sha": "434ade879194dd4bba7ec4c978816f948191e5c6b3373725cc4f7c97e814da10", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "bbd0ed5ed0a4b889c7f679087182d497559425cf2a3281cf29bf44fd883efa96", - "start_line": 44, - "name": "keyfind", - "arity": 2 - }, - "list_channels/1:125": { - "line": 125, - "guard": null, - "pattern": "socket_pid", - "kind": "def", - "end_line": 135, - "ast_sha": "43d0a778f77d5d9f68ad56eece998bc8bf2216ad48c2120aa61493e69494b89e", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "918c15d4cb8ad5b562eceb19e4e78d7dbaa7bbc4155048f60b622ca3a299e166", - "start_line": 125, - "name": "list_channels", - "arity": 1 - }, - "list_sockets/0:37": { - "line": 37, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 40, - "ast_sha": "554271f1cdb8b0b25f901529782b908560fbd4e7967e3cdd1ccf02e905d70395", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "c93e563fb86afdff3e03e4e2d919cbd21ea8eb145db4b5c40addb01001d2db1e", - "start_line": 37, - "name": "list_sockets", - "arity": 0 - }, - "socket/1:159": { - "line": 159, - "guard": null, - "pattern": "channel_pid", - "kind": "def", - "end_line": 166, - "ast_sha": "182d9559f02bcc7d094ea37b9f03b10de2599ebbecf700c63ffd27fe28170347", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "db2fc4ab37f5dea6b62fd8b5321dbcf92f7e1ce690eab3346c0a143774fbccc3", - "start_line": 159, - "name": "socket", - "arity": 1 - }, - "socket_process?/1:77": { - "line": 77, - "guard": null, - "pattern": "pid", - "kind": "def", - "end_line": 78, - "ast_sha": "51e8720aae90202230e646a1e9f859b7ec69f2e9df38c474047a2d35d87efcef", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "b3a0cfe1b9b56ec63d700b8a6fa2ebbfa81c521116040ca548c31ab511b37044", - "start_line": 77, - "name": "socket_process?", - "arity": 1 - }, - "socket_process_dict/1:51": { - "line": 51, - "guard": null, - "pattern": "pid", - "kind": "defp", - "end_line": 59, - "ast_sha": "5a664c9d9babe772142eabb458fa697cc5878095f21dd2a4c2f37472c4267146", - "source_file": "lib/phoenix/debug.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/debug.ex", - "source_sha": "e22f7e231d9ebf00e69f3d2a7c790ef1c36e4730e5ffe9a5f439a842b967fe08", - "start_line": 51, - "name": "socket_process_dict", - "arity": 1 - } - }, - "Phoenix.Socket.V2.JSONSerializer": { - "byte_size!/3:145": { - "line": 145, - "guard": null, - "pattern": "bin, kind, max", - "kind": "defp", - "end_line": 156, - "ast_sha": "dcb2211b98f9fb0ca4f94d59dcd8a5c035794678e7532e561324e280810a724d", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "462b73fa8328b9d0f2ec2def5ed9997815901048c2bc9d718621bb516dd50b8d", - "start_line": 145, - "name": "byte_size!", - "arity": 3 - }, - "decode!/2:105": { - "line": 105, - "guard": null, - "pattern": "raw_message, opts", - "kind": "def", - "end_line": 108, - "ast_sha": "b5b36550af6e6cf8dd8b69961191d84f0b127fea5f062f9ef1745115d9a6a4b1", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "5f2b4329bc410d4146f86856c1f95fb44b3c5944efe04e08ce83f3ac49fbf81c", - "start_line": 105, - "name": "decode!", - "arity": 2 - }, - "decode_binary/1:124": { - "line": 124, - "guard": null, - "pattern": "<<0::integer-size(8), join_ref_size::integer-size(8), ref_size::integer-size(8),\n topic_size::integer-size(8), event_size::integer-size(8), join_ref::binary-size(join_ref_size),\n ref::binary-size(ref_size), topic::binary-size(topic_size), event::binary-size(event_size),\n data::binary>>", - "kind": "defp", - "end_line": 141, - "ast_sha": "2e28f5660f50dcecd6bfd0ae4e582169d2f9ca5143d311c489493b0ab8c7a14c", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "1648a4c908a36e570caed93cf53ac89d87af1dece63736aebb6f91383d8bfebd", - "start_line": 124, - "name": "decode_binary", - "arity": 1 - }, - "decode_text/1:112": { - "line": 112, - "guard": null, - "pattern": "raw_message", - "kind": "defp", - "end_line": 120, - "ast_sha": "eb5f8319d36ed3d2a7578f8b279fa49038333c143d3bf06b0cbf8429d1984107", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "e161fffae7ef749e1bbdff31b4c3ec988db00ef442faae4cc633f4598f681610", - "start_line": 112, - "name": "decode_text", - "arity": 1 - }, - "encode!/1:100": { - "line": 100, - "guard": null, - "pattern": "%Phoenix.Socket.Message{payload: invalid}", - "kind": "def", - "end_line": 101, - "ast_sha": "992bf9ccc2a86c62f6695eefa135f662a161e74d92c2ea82a22c71a92c91ccaf", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "dbf7b3ea6746cc6ab4566d550ba38673d6adcfa0c18b24d759f55832f26a18f0", - "start_line": 100, - "name": "encode!", - "arity": 1 - }, - "encode!/1:38": { - "line": 38, - "guard": null, - "pattern": "%Phoenix.Socket.Reply{payload: {:binary, data}} = reply", - "kind": "def", - "end_line": 60, - "ast_sha": "8d784ee47fc52e3b2b1c3763dba52a034b0f0874d3a2f2001b8c0cbb5e0729cf", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "5ccabc0d2e3c48f79390507d5bdacc9f5f2cfe7a54070eba9cc0cebf93b88c21", - "start_line": 38, - "name": "encode!", - "arity": 1 - }, - "encode!/1:63": { - "line": 63, - "guard": null, - "pattern": "%Phoenix.Socket.Reply{} = reply", - "kind": "def", - "end_line": 72, - "ast_sha": "e9f97c2df76b3015ed9c51a610c973fb91022132a3a6df72d1cb5288b241fe1c", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "164f45776f4fb006dfab1e25c7bc1c290a45b982b295153b8d39e2953f745aba", - "start_line": 63, - "name": "encode!", - "arity": 1 - }, - "encode!/1:75": { - "line": 75, - "guard": null, - "pattern": "%Phoenix.Socket.Message{payload: {:binary, data}} = msg", - "kind": "def", - "end_line": 92, - "ast_sha": "0460918667c2fc73898b1838a7ea5d05090fd6977c4193f0a50a3f2f7b7d4dff", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "63049e138a7bf446e4641abf52e4911d9e17072b553da1ed9548fbbdfa49599b", - "start_line": 75, - "name": "encode!", - "arity": 1 - }, - "encode!/1:95": { - "line": 95, - "guard": null, - "pattern": "%Phoenix.Socket.Message{payload: %{}} = msg", - "kind": "def", - "end_line": 97, - "ast_sha": "a49db4bf7efa65286a482c84e5a94671decf73da4f6afd9d84a05839b37f719d", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "381150b7d5fc91a60bd54b4a7ef66849be6b911e30afda7c5583ca7e85238603", - "start_line": 95, - "name": "encode!", - "arity": 1 - }, - "fastlane!/1:12": { - "line": 12, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{payload: {:binary, data}} = msg", - "kind": "def", - "end_line": 25, - "ast_sha": "36e72cb0c91fd9ff4dca6de9a7129d39c37ab4afc0045df6cce53a9dd1d65d88", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "9a6abe26d05df78b930e0bf665e5420ed0d32dab241d0e9ce4e2e0e72f4fb478", - "start_line": 12, - "name": "fastlane!", - "arity": 1 - }, - "fastlane!/1:28": { - "line": 28, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{payload: %{}} = msg", - "kind": "def", - "end_line": 30, - "ast_sha": "e298c2e4121da571e5c7eb116790bddd8be8f1602f6d800b1a4360bdb38043b8", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "b8ff3519270248d9a343830ff81f37415db323049d53eed55a7bfc61db690435", - "start_line": 28, - "name": "fastlane!", - "arity": 1 - }, - "fastlane!/1:33": { - "line": 33, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{payload: invalid}", - "kind": "def", - "end_line": 34, - "ast_sha": "fdcf5996005faf80269f682ecb1237e5a894520bb3b7ddfc807dea14a986021f", - "source_file": "lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v2_json_serializer.ex", - "source_sha": "de334dec22f7a4d0c1ad918ae21b8d98d3cb007a37fa34009f82f8cebc379bce", - "start_line": 33, - "name": "fastlane!", - "arity": 1 - } - }, - "Phoenix.MissingParamError": { - "__struct__/0:32": { - "line": 32, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 32, - "ast_sha": "c5d30ef2f9fbbaa5805526071857dbc9afac5c74ac46e170f7290957c8bdd5df", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", - "start_line": 32, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:32": { - "line": 32, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 32, - "ast_sha": "f3ca7d7758f206f046b9f7b4c9516bbf1c42697b88af43fddaecf08408e9bbfb", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", - "start_line": 32, - "name": "__struct__", - "arity": 1 - }, - "exception/1:34": { - "line": 34, - "guard": null, - "pattern": "[key: value]", - "kind": "def", - "end_line": 37, - "ast_sha": "bb13e0f73605fba6881169ef192e9d6ed239dfe21dddba659a91bcce73e523d3", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "9007b3b150c884086a2c45430c1d2601772eb998acbda7416c22776a7e2c3850", - "start_line": 34, - "name": "exception", - "arity": 1 - }, - "message/1:32": { - "line": 32, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 32, - "ast_sha": "090ff7a37a5f95b7f7f5e0beeb3a5d8b7a0970da0b4637aa7f983a246e238b20", - "source_file": "lib/phoenix/exceptions.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/exceptions.ex", - "source_sha": "33ed3f0889d5f3c3c7870479f0a98f42161a9dcf6e4c021a1ca9a5d15fee764c", - "start_line": 32, - "name": "message", - "arity": 1 - } - }, - "Inspect.Phoenix.Socket.Message": { - "__impl__/1:39": { - "line": 39, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 39, - "ast_sha": "61ddaabe83b7fa6d2d5b0325141cb78fe19864f80709190ab5362c655d893a64", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "b33a5b76c8e50806e8939064f73c6a0be1451dd778529947d59a057d8a841020", - "start_line": 39, - "name": "__impl__", - "arity": 1 - }, - "inspect/2:40": { - "line": 40, - "guard": null, - "pattern": "%Phoenix.Socket.Message{} = msg, opts", - "kind": "def", - "end_line": 42, - "ast_sha": "2be110e8204966ea6a90984b6d20a36abc8381042e84fd8a7ae2812b445d02fc", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "9c581032c7a5d6d07a2dc518882c43aeef93c0b461eaaa15e7c37756a9bb6ed5", - "start_line": 40, - "name": "inspect", - "arity": 2 - }, - "process_message/1:45": { - "line": 45, - "guard": "is_map(payload)", - "pattern": "%{payload: payload} = msg", - "kind": "defp", - "end_line": 46, - "ast_sha": "ffc6157b12e9b904dd4caedb0b89286a4bcbbfd58a9b4c5bd25e98a7f65ea09b", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "09bd5650a0df3c5c8ebb489201a8e42fbd7b5de9f0c0ade5d91bfa14675676ca", - "start_line": 45, - "name": "process_message", - "arity": 1 - }, - "process_message/1:49": { - "line": 49, - "guard": null, - "pattern": "msg", - "kind": "defp", - "end_line": 49, - "ast_sha": "26162abdc7663ac0db6566dec6a04f2e634b5f06a22cefe8bfac806a69c7f29c", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "09fb43158895c443864ffdfde12ddd6fb8c58852916639f39249dbe1a848e005", - "start_line": 49, - "name": "process_message", - "arity": 1 - } - }, - "Phoenix.CodeReloader": { - "call/2:112": { - "line": 112, - "guard": null, - "pattern": "conn, opts", - "kind": "def", - "end_line": 121, - "ast_sha": "92e88fa7f80980dc39d16a61760f927053201d3d75eadbb70f85550cac01869d", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "33870511f54712713ad2a20dc0d5ae84933a119e1653ff4836bcb519aa59f206", - "start_line": 112, - "name": "call", - "arity": 2 - }, - "child_spec/1:75": { - "line": 75, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 75, - "ast_sha": "157b79c877260fdec0ca9b487c797af86b212136d8251b8f8ca1332ed78a21a0", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "ea9cbc176c4b8022b128fa69fd9ac7c96b9b5a1dec5a91bab6fbbd7bbc5e0218", - "start_line": 75, - "name": "child_spec", - "arity": 1 - }, - "format_output/1:330": { - "line": 330, - "guard": null, - "pattern": "output", - "kind": "defp", - "end_line": 334, - "ast_sha": "43ad73a6516f2d2780398ef645ef39f7383717bf5c784a900a303a47f749a7c0", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "676174e47f3d7ee6421b82c6373fd465d602af749e86ad7591a51e16b0fe8dab", - "start_line": 330, - "name": "format_output", - "arity": 1 - }, - "init/1:105": { - "line": 105, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 106, - "ast_sha": "710c460cf431317dce006a40afd9c90eb207fd1057bf038cdaffd9d053e2555e", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "0a2bae7ff64ecc411e1cca12df9b09b3fb31e0f29a7d260293d227c4213fb33c", - "start_line": 105, - "name": "init", - "arity": 1 - }, - "reload!/2:63": { - "line": 63, - "guard": null, - "pattern": "endpoint, opts", - "kind": "def", - "end_line": 63, - "ast_sha": "89122a0d1ea41bd70f38d313ca8313c2167b6f669ce906ffb18e2e4c84321b0f", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "afec2cac81890b9f7f9ef578b3296a0740b9209b79664f897b8069c33c451a45", - "start_line": 63, - "name": "reload!", - "arity": 2 - }, - "reload/1:55": { - "line": 55, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 55, - "ast_sha": "949f861f8f9c5ce8c9445d3156fc7508624bd7c76bdd28025fabd0ed9cb6560d", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "5ae7da26c62cc4c740bc529f031e7e129b98fae25f8443528a095b597a4ce9b7", - "start_line": 55, - "name": "reload", - "arity": 1 - }, - "reload/2:55": { - "line": 55, - "guard": null, - "pattern": "endpoint, opts", - "kind": "def", - "end_line": 56, - "ast_sha": "5f09be9711c4170053f6916f97e23b7986f5b47ecb8903fb91f27c808e5543ab", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "be5e3b1058820908e5d4354a517630f83ba12d60612a9f3684c304bf9d24f431", - "start_line": 55, - "name": "reload", - "arity": 2 - }, - "remove_ansi_escapes/1:337": { - "line": 337, - "guard": null, - "pattern": "text", - "kind": "defp", - "end_line": 338, - "ast_sha": "41c59c6f30acdce644c743c2310bd2749ee8acab4facd7591d994ed06cebdfa1", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "982710449f8b70f798d04c8e51a78f2c363ca13ae4e605a5133ec4ab04b9f1cf", - "start_line": 337, - "name": "remove_ansi_escapes", - "arity": 1 - }, - "sync/0:71": { - "line": 71, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 71, - "ast_sha": "dacc0bf02a2c7f55b44ddcb27e22a206334997df6e7db58833aafe0c39748b73", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "b531ec1c8134ed7a6230e8b03459bc11453a4aab6a7064f6465dcd9a2920ddb7", - "start_line": 71, - "name": "sync", - "arity": 0 - }, - "template/1:125": { - "line": 125, - "guard": null, - "pattern": "output", - "kind": "defp", - "end_line": 323, - "ast_sha": "17b57f4a866b7982d8629e28b6670d3b5e429acdec0c3bd885ca7827e6494c9b", - "source_file": "lib/phoenix/code_reloader.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader.ex", - "source_sha": "63157a57556b7c0181ba31870aadb52209a3d20e080bc8b4d60fed53b8fa7140", - "start_line": 125, - "name": "template", - "arity": 1 - } - }, - "Phoenix.Socket.InvalidMessageError": { - "__struct__/0:254": { - "line": 254, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 254, - "ast_sha": "ea62c9d2410f46fd24e0e05e724e8607dcad2c1ec4d7c919dd53084b8a06e3af", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", - "start_line": 254, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:254": { - "line": 254, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 254, - "ast_sha": "edb0c33423262545a059c009c1de30c0614b36b9eadaedf9b78a7c407cefb581", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", - "start_line": 254, - "name": "__struct__", - "arity": 1 - }, - "exception/1:254": { - "line": 254, - "guard": "is_list(args)", - "pattern": "args", - "kind": "def", - "end_line": 254, - "ast_sha": "51af484f83a1353124d7d452c9158df456767cb18c090e7df4cfa3c66f5a1104", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", - "start_line": 254, - "name": "exception", - "arity": 1 - }, - "message/1:254": { - "line": 254, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 254, - "ast_sha": "021eb93373fbfda6c5362413dea869d354e8b9afb6b10aff6c711a896a51649b", - "source_file": "lib/phoenix/socket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket.ex", - "source_sha": "d1fdcea3203f40480f4869a20fe1544a1969025fda13f200508b47df366a4b24", - "start_line": 254, - "name": "message", - "arity": 1 - } - }, - "Phoenix.Socket.V1.JSONSerializer": { - "decode!/2:30": { - "line": 30, - "guard": null, - "pattern": "message, _opts", - "kind": "def", - "end_line": 38, - "ast_sha": "f7c70d6459b39870de76064b9a1f87e3235c779efe142501ac2c9250a44fcbde", - "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_sha": "c9b87c2c0cff44f00c3edabded019a7eb8ed3b486fc36cd94fa014e1aa2a65c4", - "start_line": 30, - "name": "decode!", - "arity": 2 - }, - "encode!/1:14": { - "line": 14, - "guard": null, - "pattern": "%Phoenix.Socket.Reply{} = reply", - "kind": "def", - "end_line": 22, - "ast_sha": "cc0d77e763a0a9b4c82f3f4d6e1ac520ef4bb50c89b86bf3f145c8d38f435ff0", - "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_sha": "08726fa9def1d4845126e46caecbb6497cf02053c83eb5a8f9f7095d793e54b9", - "start_line": 14, - "name": "encode!", - "arity": 1 - }, - "encode!/1:25": { - "line": 25, - "guard": null, - "pattern": "%Phoenix.Socket.Message{} = map", - "kind": "def", - "end_line": 26, - "ast_sha": "3f74baa7b8cde19788cab08629e2e66e162a416ea99cee4ba1130ae0a4dcb4ae", - "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_sha": "9570c414e26c3c24803eafb6ef55605fbe18eec0a050fda2094d9a93ea69a9fd", - "start_line": 25, - "name": "encode!", - "arity": 1 - }, - "encode_v1_fields_only/1:42": { - "line": 42, - "guard": null, - "pattern": "%Phoenix.Socket.Message{} = msg", - "kind": "defp", - "end_line": 45, - "ast_sha": "e33449ad47b5627ff4471e9d85028552c54dccca51130f3c66241a4fc5a6d3ad", - "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_sha": "3fd46b2e7fe64f52df5587eb889af031da3c8b2ec06567291280c413cf5475fd", - "start_line": 42, - "name": "encode_v1_fields_only", - "arity": 1 - }, - "fastlane!/1:8": { - "line": 8, - "guard": null, - "pattern": "%Phoenix.Socket.Broadcast{} = msg", - "kind": "def", - "end_line": 10, - "ast_sha": "2dec9e4efe8c4968e9e6a9317e3e7e18292caaec62cfb80d826ef10534299d8c", - "source_file": "lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/serializers/v1_json_serializer.ex", - "source_sha": "b8a2e12c9975d4c62ea5fc1f05d58811c2554b12035aabb0723ee1a381141671", - "start_line": 8, - "name": "fastlane!", - "arity": 1 - } - }, - "Phoenix.Socket.Message": { - "__struct__/0:17": { - "line": 17, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 17, - "ast_sha": "3cd41b4fe8e17a5f901f4b6223067542c2e51491989c43924574d4e12923d25b", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "d6e0b680dc4c9b7890d7b131438caca2eebe76eecfadf9f1c8b855ac3a27461c", - "start_line": 17, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:17": { - "line": 17, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 17, - "ast_sha": "bcc70fed8a3e8988742eeefd236854846ef724aa920572ec68b07feffe42bea8", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "d6e0b680dc4c9b7890d7b131438caca2eebe76eecfadf9f1c8b855ac3a27461c", - "start_line": 17, - "name": "__struct__", - "arity": 1 - }, - "from_map!/1:24": { - "line": 24, - "guard": "is_map(map)", - "pattern": "map", - "kind": "def", - "end_line": 35, - "ast_sha": "fa9bc6a97967bfa479295132eb76e7e1db43017370d0cbe2465efe0b98125bce", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "22370285c52bf164b1784903f9dcc1f75b6a96aabd4989d897124574d51eb0f3", - "start_line": 24, - "name": "from_map!", - "arity": 1 - } - }, - "Phoenix.Controller.Pipeline": { - "__action_fallback__/2:39": { - "line": 39, - "guard": null, - "pattern": "plug, caller", - "kind": "def", - "end_line": 41, - "ast_sha": "06b208dc9082d2dc0a64e783a2df363704e113834865714b318ad77d3f6bf675", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "174cc72afeb9e0bef2eda88d64a89e4c41bf89851599b17f897616f5a9772a65", - "start_line": 39, - "name": "__action_fallback__", - "arity": 2 - }, - "__before_compile__/1:75": { - "line": 75, - "guard": null, - "pattern": "env", - "kind": "defmacro", - "end_line": 116, - "ast_sha": "445ced3dec7c256ad18f37d95e32c3a0db23f25fad11a00cdc0c509f9761a6e8", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "95c7b09f0bfe7685f8e64cfc64111f5d5c43ce690931ca64414e46a8b4ead5da", - "start_line": 75, - "name": "__before_compile__", - "arity": 1 - }, - "__catch__/5:144": { - "line": 144, - "guard": null, - "pattern": "%Plug.Conn{}, :function_clause, controller, action, [{controller, action, [%Plug.Conn{} | _] = action_args, _loc} | _] = stack", - "kind": "def", - "end_line": 152, - "ast_sha": "0098645acf12369cf6bf41ebeca20dd9764e898de5a04a137bd3685536043a81", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "396a962c0b53d109c257e22f2392d91a547611ea0fca59005f86a33974f37933", - "start_line": 144, - "name": "__catch__", - "arity": 5 - }, - "__catch__/5:155": { - "line": 155, - "guard": null, - "pattern": "%Plug.Conn{} = conn, reason, _controller, _action, stack", - "kind": "def", - "end_line": 156, - "ast_sha": "72c6902c211ccba529a35ba69669009fb642214bed65b9da816f6193892822de", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "e0f1e6b9f35878584f1f12e82f73ab13e3c2b1f4ded9246e846bd1dec666bad8", - "start_line": 155, - "name": "__catch__", - "arity": 5 - }, - "__using__/1:5": { - "line": 5, - "guard": null, - "pattern": "_", - "kind": "defmacro", - "end_line": 5, - "ast_sha": "7426f3e1666b6eae7333637eb833ccc34d19d04dab0f616763c7542c1ca0a2be", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "7076efa06766215d075f9a82942cbcf1918cb89191069441c724601520f5a5ac", - "start_line": 5, - "name": "__using__", - "arity": 1 - }, - "build_fallback/1:121": { - "line": 121, - "guard": null, - "pattern": ":unregistered", - "kind": "defp", - "end_line": 121, - "ast_sha": "7dd2b1626704645b197be5f3f960059b1486526b7cbc12030dba244d880d9782", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "6b59d0f73c96eae6c9fc7ef1cf77877f9f15e31c1cf5c7317e3c2364885beec3", - "start_line": 121, - "name": "build_fallback", - "arity": 1 - }, - "build_fallback/1:125": { - "line": 125, - "guard": null, - "pattern": "{:module, plug}", - "kind": "defp", - "end_line": 126, - "ast_sha": "cc37d4180da676123772e67ab1bb13f7dd4f0e8cde297cb96555a3c1dd54708b", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "56656ccd071c56605e086ab0b9b024866140fb35129e61494b1df6601ca44a0b", - "start_line": 125, - "name": "build_fallback", - "arity": 1 - }, - "build_fallback/1:134": { - "line": 134, - "guard": null, - "pattern": "{:function, plug}", - "kind": "defp", - "end_line": 138, - "ast_sha": "58516224be2319ec8825adb6a819a0301ce8c4d8533d8f67da4cbfc8c3af94f6", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "626b2438ebd1e5d65377e73673fafeeccc14d1d7c69ecd8d93071b09b2f8020f", - "start_line": 134, - "name": "build_fallback", - "arity": 1 - }, - "escape_guards/1:205": { - "line": 205, - "guard": "=:=(pre_expanded, :@) or =:=(pre_expanded, :__aliases__)", - "pattern": "{pre_expanded, _, [_ | _]} = node", - "kind": "defp", - "end_line": 207, - "ast_sha": "8db78fa2f8fcb33623cd917a6e6819a45508dc4f333f8571729f3a29f8b7e99b", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "65758547cc5402a8f7d4409f7a665a5f8621f8dd664d938455495cfd752685aa", - "start_line": 205, - "name": "escape_guards", - "arity": 1 - }, - "escape_guards/1:209": { - "line": 209, - "guard": null, - "pattern": "{left, meta, right}", - "kind": "defp", - "end_line": 210, - "ast_sha": "a9a003423e7b3d8dfae63b708be371801ecbb7c20d522d3c52b627530f7f4b7f", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "7ce51890dae6a9b2426781ba713f7b9235472e1c8fc04b721d27aec8efb48384", - "start_line": 209, - "name": "escape_guards", - "arity": 1 - }, - "escape_guards/1:212": { - "line": 212, - "guard": null, - "pattern": "{left, right}", - "kind": "defp", - "end_line": 213, - "ast_sha": "8a08af24b1bc38d6ffc5a025e1c1a7257fec8c9150abc5a487aa14dc3510122e", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "f91657d86544b740a93b125abbf0e419fab23082f54cbe6f4888e6344c716b67", - "start_line": 212, - "name": "escape_guards", - "arity": 1 - }, - "escape_guards/1:215": { - "line": 215, - "guard": null, - "pattern": "[_ | _] = list", - "kind": "defp", - "end_line": 216, - "ast_sha": "b674d6ee90093ec1834da802a22b591281abe81cb13a3f739c25902fe3f94771", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "ff77fedaf895ce6f82a2a36a0343071bd8a1da162a782009bd0380e861505713", - "start_line": 215, - "name": "escape_guards", - "arity": 1 - }, - "escape_guards/1:218": { - "line": 218, - "guard": null, - "pattern": "node", - "kind": "defp", - "end_line": 219, - "ast_sha": "9cecbc01864de67a1fd2e8ea65a41d43a1f4ebfcf6b72a419bb519b29fd6423c", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "b273eda3cb298f56cb2fe238629a7be04d2659cc29f5ea153e17be4b249ab1e0", - "start_line": 218, - "name": "escape_guards", - "arity": 1 - }, - "expand_alias/2:200": { - "line": 200, - "guard": null, - "pattern": "{:__aliases__, _, _} = alias, env", - "kind": "defp", - "end_line": 201, - "ast_sha": "7b31396c92d10375302e2d9bf348c3d9bb9889836f3d52344ee0111ec8719958", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "7599dd70b9a94c532aa4050ea2895b5b7ceb706318007c89ad50955b47a88598", - "start_line": 200, - "name": "expand_alias", - "arity": 2 - }, - "expand_alias/2:203": { - "line": 203, - "guard": null, - "pattern": "other, _env", - "kind": "defp", - "end_line": 203, - "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", - "start_line": 203, - "name": "expand_alias", - "arity": 2 - }, - "plug/1:164": { - "line": 164, - "guard": null, - "pattern": "{:when, _, [plug, guards]}", - "kind": "defmacro", - "end_line": 164, - "ast_sha": "88711d46faecc8f3fd49ef45f1a49b246cc6c67524f6f8aa05044073bcfc8575", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "bc70ae4a9260f827b1eec9027cf806b7c31eaea3150f727fa8c2a6ab14495c6d", - "start_line": 164, - "name": "plug", - "arity": 1 - }, - "plug/1:166": { - "line": 166, - "guard": null, - "pattern": "plug", - "kind": "defmacro", - "end_line": 166, - "ast_sha": "bac46bd8fd4b483bfea6f4dc6e920088432d73512521065d6952ad66a49a36d0", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "b2f60dac74b5c7502487d00505619f18657c433722f47671d5a2f2eed29ab9f4", - "start_line": 166, - "name": "plug", - "arity": 1 - }, - "plug/2:174": { - "line": 174, - "guard": null, - "pattern": "plug, {:when, _, [opts, guards]}", - "kind": "defmacro", - "end_line": 174, - "ast_sha": "80d383113c354e481627f9e1eed28f54c7e872eed310c02a3447d318a7643b72", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "6478f28b60eb5bff072305bcc94c958d50a8a3ded74dc02335ef9cf355099567", - "start_line": 174, - "name": "plug", - "arity": 2 - }, - "plug/2:176": { - "line": 176, - "guard": null, - "pattern": "plug, opts", - "kind": "defmacro", - "end_line": 176, - "ast_sha": "2c51455e139b9901eff58b87d1da70607a2c3cd6d3a0bb3e2ea6501487c4257d", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "cbc6c1ced5395f274350191bc318f472f0359bc7541a32a16913a07a9046a5f7", - "start_line": 176, - "name": "plug", - "arity": 2 - }, - "plug/4:178": { - "line": 178, - "guard": null, - "pattern": "plug, opts, guards, caller", - "kind": "defp", - "end_line": 196, - "ast_sha": "2d17d89bfc9b68521569670547cbc8b60b928bb9140ea7db060004622cc77509", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "7959fb9e6da8bb721d243c2fcad694585d26e0ace9c7ca9b568e85de1f2075f7", - "start_line": 178, - "name": "plug", - "arity": 4 - }, - "validate_fallback/3:51": { - "line": 51, - "guard": null, - "pattern": "plug, module, fallback", - "kind": "def", - "end_line": 69, - "ast_sha": "6e4dcf7def2250f4793dd91452c1a35f5a2b31501f12561ae26c124a6f747494", - "source_file": "lib/phoenix/controller/pipeline.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/controller/pipeline.ex", - "source_sha": "2006e85d48cc9e4f32729e9459fcbcd3374129272687b20ffe29a3ccabc268b8", - "start_line": 51, - "name": "validate_fallback", - "arity": 3 - } - }, - "Mix.Tasks.Phx.Server": { - "iex_running?/0:39": { - "line": 39, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 40, - "ast_sha": "a8c0a92ccf3daaac170068d669439b90af0402053486f6b1335499cee7776f1b", - "source_file": "lib/mix/tasks/phx.server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "source_sha": "75d7f916f1bf0030e3de32da6d6e5c6cc1366596eefa58cd42f9d3f4723ae167", - "start_line": 39, - "name": "iex_running?", - "arity": 0 - }, - "open_args/1:43": { - "line": 43, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 48, - "ast_sha": "7410253064a1d200d713395b29e8503fa43733dd620ff35e578f264bff79e902", - "source_file": "lib/mix/tasks/phx.server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "source_sha": "1afe9b04c28fcf75d02f0514d50175a7463f0c16362eb29820a752a53220fdf4", - "start_line": 43, - "name": "open_args", - "arity": 1 - }, - "run/1:34": { - "line": 34, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 36, - "ast_sha": "8c3140247646c6d46700f7f532ec6593d60a72979d8c8f98c883198c5a3e93a1", - "source_file": "lib/mix/tasks/phx.server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "source_sha": "d58f8cc02ef2e1e11f7e6bb15bb1eb97bf275ceb8222fbc83ee638b747aef823", - "start_line": 34, - "name": "run", - "arity": 1 - }, - "run_args/0:52": { - "line": 52, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 53, - "ast_sha": "5560f88f28bc21a7607827f222bd5df115387f733ededd548b8451e2b03dabd1", - "source_file": "lib/mix/tasks/phx.server.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.server.ex", - "source_sha": "60a441ba24d1e1f4048f52377c93aa98e2d68156c3b76704150687451b70c758", - "start_line": 52, - "name": "run_args", - "arity": 0 - } - }, - "Mix.Tasks.Phx.Routes": { - "app_mod/2:165": { - "line": 165, - "guard": null, - "pattern": "base, name", - "kind": "defp", - "end_line": 165, - "ast_sha": "37557354fe72d15282c69004b1b9a5baf4aa440576fe6e07d41e0107f5e0a95c", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "4dd2b75435a4120f3e53b665ea6db79457889a533bba886c49c1d52edc4ab8e9", - "start_line": 165, - "name": "app_mod", - "arity": 2 - }, - "endpoint/2:117": { - "line": 117, - "guard": null, - "pattern": "nil, base", - "kind": "defp", - "end_line": 118, - "ast_sha": "886e2a23ec167fbb0918e351a22d052f06203279f9bf25eb3223b0053922d469", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "4bc942765174f4e31b59fdf6bb2f59dec0a876e3176331dbfb7c84744bb12d3b", - "start_line": 117, - "name": "endpoint", - "arity": 2 - }, - "endpoint/2:121": { - "line": 121, - "guard": null, - "pattern": "module, _base", - "kind": "defp", - "end_line": 122, - "ast_sha": "0ef670ff48965f811438e4dcc513edb14701219ecd12ea0f17590a680c561676", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "2986a5a4ff76653483c105a03875a8d7d09ce8d92a617e8417501b25da3a9e46", - "start_line": 121, - "name": "endpoint", - "arity": 2 - }, - "get_file_path/1:169": { - "line": 169, - "guard": null, - "pattern": "module_name", - "kind": "defp", - "end_line": 172, - "ast_sha": "752b52144fd6709a783dfa6e11ca1da4937751a69ecae78fdf20a4d02fd383ca", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "d536479559305ed23ac403db2c92127f72a34ec97995a67f80d66470623939ac", - "start_line": 169, - "name": "get_file_path", - "arity": 1 - }, - "get_line_number/2:175": { - "line": 175, - "guard": null, - "pattern": "_, nil", - "kind": "defp", - "end_line": 175, - "ast_sha": "6b1d0d9d008c27a3962b992b4fe8cee78cae099b75857813966458a15418eb2f", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "9d0a78b70e73f4657bf480f6cbe1cde2944c01975a31ebe18d4ce2a766a69b23", - "start_line": 175, - "name": "get_line_number", - "arity": 2 - }, - "get_line_number/2:177": { - "line": 177, - "guard": null, - "pattern": "module, function_name", - "kind": "defp", - "end_line": 188, - "ast_sha": "52b001054fb2d1fe810dedb68ad28e608140b00ab9cbdcc5ab7ec288f269766f", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "60f256d625b7fe039f92875c37f42e3bbc672e6a1837f16c5639747500655ca1", - "start_line": 177, - "name": "get_line_number", - "arity": 2 - }, - "get_url_info/2:92": { - "line": 92, - "guard": null, - "pattern": "url, {router_mod, opts}", - "kind": "def", - "end_line": 113, - "ast_sha": "e4368964501f8ecad2761fb4febcc6d82414e6f4614b35ec9c5a9325842ad2cd", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "40b436c07c96680909f4c7a76e27867c0778e0e096874a4c07b7b01ef859c3f4", - "start_line": 92, - "name": "get_url_info", - "arity": 2 - }, - "loaded/1:161": { - "line": 161, - "guard": null, - "pattern": "module", - "kind": "defp", - "end_line": 162, - "ast_sha": "3cd38093fdcb501e0a4252b9e8ff5435bf897a46d4ce4d0fbba3b743a0d5c0e0", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "8683255157c8619929a7ee0d973f6fc57fecf9019b9ed3cddef3aba24a30816f", - "start_line": 161, - "name": "loaded", - "arity": 1 - }, - "router/2:125": { - "line": 125, - "guard": null, - "pattern": "nil, base", - "kind": "defp", - "end_line": 144, - "ast_sha": "71daa49abcfd41b3b786bc153fb3251e2ffbc9b5d737db540e1da2f09d53d678", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "10c9e8d983c83a90fed238c9648f0f154b28d712f633e69ef5f275e2be60c2b2", - "start_line": 125, - "name": "router", - "arity": 2 - }, - "router/2:156": { - "line": 156, - "guard": null, - "pattern": "router_name, _base", - "kind": "defp", - "end_line": 158, - "ast_sha": "9c1613ec19b41c543ee61dc754aecca1c9f172c2fb28ec610100562327681277", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "de7dc7fc8b0f0543d7c4b14f67f361397d7f9e0339f5d1828bce1f482226debe", - "start_line": 156, - "name": "router", - "arity": 2 - }, - "run/1:65": { - "line": 65, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 65, - "ast_sha": "e7d404e1fd06cc8abe98b523b47a30814ab7aaf77a4f5c131d192d64f8544aa0", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "09d8cf79b07f04b41f287c6fe1e8dd75d94448c458a9922a655414788597375f", - "start_line": 65, - "name": "run", - "arity": 1 - }, - "run/2:65": { - "line": 65, - "guard": null, - "pattern": "args, base", - "kind": "def", - "end_line": 88, - "ast_sha": "c8cabb09a8b612fba751cdf75814fab164fff9289c9802614a3ad47d0a7850d8", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "169ef3cd69be05ed4fcae3231ec88e3d3119fa83252ba771bc55ba95b8016040", - "start_line": 65, - "name": "run", - "arity": 2 - }, - "web_mod/2:167": { - "line": 167, - "guard": null, - "pattern": "base, name", - "kind": "defp", - "end_line": 167, - "ast_sha": "9ac8e17441e10b4d2d1c5d2be6f3869e112b755a4a080baccc317f20d8919bbe", - "source_file": "lib/mix/tasks/phx.routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.routes.ex", - "source_sha": "8cb627b5c416eb1b73c761fb6c7c360d6cc0b39d0b367b0a9041d555072de0fb", - "start_line": 167, - "name": "web_mod", - "arity": 2 - } - }, - "Phoenix.ConnTest": { - "receive_response/2:696": { - "line": 696, - "guard": null, - "pattern": "{:error, {_kind, exception, stack}}, expected_status", - "kind": "defp", - "end_line": 713, - "ast_sha": "79e3f022e2b2e6d75122e8e0d487ad0dc72ac5430202b8be8b2895bc08d6c1dd", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "f3aee01a761101e955a4b401988eda18d828068213ccdc03bc2ea7448b84f819", - "start_line": 696, - "name": "receive_response", - "arity": 2 - }, - "__using__/1:114": { - "line": 114, - "guard": null, - "pattern": "_", - "kind": "defmacro", - "end_line": 124, - "ast_sha": "a3e92c5a35eb9453f3df4dec848c74252ed719f3ef528cca852540330592555a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a45945ad30e4f52b120ce3682ce740a777f5294a187a464c172a864e0b71ad19", - "start_line": 114, - "name": "__using__", - "arity": 1 - }, - "response_content_type?/2:326": { - "line": 326, - "guard": null, - "pattern": "header, format", - "kind": "defp", - "end_line": 332, - "ast_sha": "132d0f2476d07e162d9fb548facdea83453a5c8829e640123ffaa6da3486b55e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "253a7e3a9d27e211f3cd03c94d30bd42f079ba295bb195cd8366abd47e0986a4", - "start_line": 326, - "name": "response_content_type?", - "arity": 2 - }, - "html_response/2:386": { - "line": 386, - "guard": null, - "pattern": "conn, status", - "kind": "def", - "end_line": 389, - "ast_sha": "1c6a53a532946535cc6a68f6e4a2da281202f232b4ae5acb7a0d7e49b57b888c", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "6206137662dd2c1eff7b52d52fbe1716281839f72479e01d89e2fe961a83bfb2", - "start_line": 386, - "name": "html_response", - "arity": 2 - }, - "dispatch/5:229": { - "line": 229, - "guard": null, - "pattern": "conn, _endpoint, method, _path_or_action, _params_or_body", - "kind": "def", - "end_line": 231, - "ast_sha": "b8e81a57ddaf2984668dc9e6d6369f6e8b7ea8d7bef8d59bd2506e1f667d082e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "ee5eff598d6afe532344ea3bc71160f57acb99e5cb119802e795b61f64be444e", - "start_line": 229, - "name": "dispatch", - "arity": 5 - }, - "options/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "92080e8dc91a68af87620f3d66bc4bdf34cb418b936fc606beafa93c2fbcf72c", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "options", - "arity": 3 - }, - "get_flash/1:278": { - "line": 278, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 278, - "ast_sha": "2b5f321f35bf1aba74655c8d2524a06c0ed0146d15fda852f9c9689e882a1b06", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "94b1f72a555a5e28d4ea6ca8b817bf06c55e0ea2c1044996fd944ebfe729be6d", - "start_line": 278, - "name": "get_flash", - "arity": 1 - }, - "clear_flash/1:299": { - "line": 299, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 299, - "ast_sha": "5adf712e3a1bd12dd2d479f90af75eb46b8b88d90761460d0dd688f637eedb11", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "ccb7dbfee3340489a3579f448b190ce40c124ee9b49c51130cfcc2d506225b1e", - "start_line": 299, - "name": "clear_flash", - "arity": 1 - }, - "patch/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "c4f9c759fa2f178280a93d6aba398a6bafa6a850978172e24f1ddf5103b32328", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "patch", - "arity": 2 - }, - "options/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "b686fccf3156c05de818fba622975fddcd6d93e4ed1ae240cda9b5b164c5ee98", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "options", - "arity": 2 - }, - "connect/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "dfc4f5f37485aeb486b8954a4147c2cfeecd5a2f5beb5811ae9380f7d77c160e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "connect", - "arity": 2 - }, - "connect/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "3e22c88bab40311012da8631985378150f2ecda9732f2e8e68f324810c5a2b17", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "connect", - "arity": 3 - }, - "put/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "a9bd6742d935df1da84558b49713a81b9e98899a597bcf8e81b7bf018a0e81bc", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "put", - "arity": 3 - }, - "text_response/2:401": { - "line": 401, - "guard": null, - "pattern": "conn, status", - "kind": "def", - "end_line": 404, - "ast_sha": "e581c1bdc26361090fd431eed08cd8be09e43226bc5d95c9d871ba33ad6bf951", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "206a9fb0c0b1ce49cd96425c2b4315b9b9fd500ac075e2c0670b2e86f26c5d2f", - "start_line": 401, - "name": "text_response", - "arity": 2 - }, - "get_flash/2:285": { - "line": 285, - "guard": null, - "pattern": "conn, key", - "kind": "def", - "end_line": 286, - "ast_sha": "376231054506fa49b8c0e652fd570cde9e2c65e489d357f73f16310fa4b1d9db", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "7b80de03329343f47c10a46f35df95e80a7d1190a3af0e838200c212d5510795", - "start_line": 285, - "name": "get_flash", - "arity": 2 - }, - "trace/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "4f755671eff6f86bb6bb14744f8fe89c1c8bc8df3aa6d2ece494f35bbdc2d249", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "trace", - "arity": 2 - }, - "recycle/2:476": { - "line": 476, - "guard": null, - "pattern": "conn, headers", - "kind": "def", - "end_line": 482, - "ast_sha": "49fa7fd9b378c8b5b60981dbc46acb70c0c600bead46abf3ab58201fc44648b5", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "5410c2068aee58546ea106e7c76dcdb79543fbf50b4d728dbcd3c77ce8da9c7c", - "start_line": 476, - "name": "recycle", - "arity": 2 - }, - "trace/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "767ac08c31c0390acafd6fcfd90c5362b38dc87eb0a315866475288fe65faa08", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "trace", - "arity": 3 - }, - "redirected_to/2:440": { - "line": 440, - "guard": null, - "pattern": "%Plug.Conn{state: :unset}, _status", - "kind": "def", - "end_line": 441, - "ast_sha": "3e20da8802702a243751e270986092180c708ff35dbdfa61236703d763df505f", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "26780908faedc7c7aa642a812126494afe3b15f6ae993752161a2ed67d77242a", - "start_line": 440, - "name": "redirected_to", - "arity": 2 - }, - "get/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "ae1cd704b6501b7ef30bf1f30765efd03efc9fb67715ac162acc970e294cb398", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "get", - "arity": 3 - }, - "redirected_params/2:590": { - "line": 590, - "guard": null, - "pattern": "%Plug.Conn{} = conn, status", - "kind": "def", - "end_line": 599, - "ast_sha": "1ffe1ca814e3829cbb0d5a27fc2a6a4a86c1282b62d47ebe2773f35b624062e6", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "ee0d61050867170340711af59cd895f6d5ea817e8d0ff56499c2153f600e7344", - "start_line": 590, - "name": "redirected_params", - "arity": 2 - }, - "patch/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "14da838412bcdc41be679905bab880636f571b5f9723174e2696b90400abe0a0", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "patch", - "arity": 3 - }, - "redirected_to/2:444": { - "line": 444, - "guard": "is_atom(status)", - "pattern": "conn, status", - "kind": "def", - "end_line": 445, - "ast_sha": "1192555a0c9a217eee278ccfc86539f384f9f5e66931ba587e0c8b7d914a365e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "f9332c26502a8cb2e626920904af2559501cb6f476c7bede5e7fac144cfe1892", - "start_line": 444, - "name": "redirected_to", - "arity": 2 - }, - "copy_headers/3:485": { - "line": 485, - "guard": null, - "pattern": "conn, headers, copy", - "kind": "defp", - "end_line": 487, - "ast_sha": "a7edebb6414559fc2d7db136c462909e95f39cc5ca9c2a317c2c0aa62214ceae", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "32fc28d540a05b5a5a41c200841f3c7187828f0880d05ecf2c6eb442922e1f71", - "start_line": 485, - "name": "copy_headers", - "arity": 3 - }, - "put_req_cookie/3:259": { - "line": 259, - "guard": null, - "pattern": "conn, key, value", - "kind": "def", - "end_line": 259, - "ast_sha": "54a871d9ee003764c3f7937b1a58b3815bffc1d499fb14fad64f33397379df0a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "6cfae39ed40985e161f4bdec639ca75024d967dcd2adf387f97ad67d0c1a4f34", - "start_line": 259, - "name": "put_req_cookie", - "arity": 3 - }, - "put/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "ceb30d6ec48925f6d943eabca79b3b56e1c8fc569dd2f3ac98a06773ab2d3dcb", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "put", - "arity": 2 - }, - "init_test_session/2:253": { - "line": 253, - "guard": null, - "pattern": "conn, session", - "kind": "def", - "end_line": 253, - "ast_sha": "38b57b7e9a6e02a69a55c7b069272883ab929d79843516537cb8b6328ad31c2d", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "dc9bc57ce33b405fbef42c82bd3efaa4f91979ba6ddef12b6f383cb9e84a10e8", - "start_line": 253, - "name": "init_test_session", - "arity": 2 - }, - "parse_content_type/1:337": { - "line": 337, - "guard": null, - "pattern": "header", - "kind": "defp", - "end_line": 341, - "ast_sha": "71069600c4d5fb75dbb931ee9277cea59e9f1c530526fb144cf778a9c243536f", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a019e34f386418dc6ed3394b74ca7f64395ecd215dc97ab621408ee4ef1fae67", - "start_line": 337, - "name": "parse_content_type", - "arity": 1 - }, - "build_conn/3:151": { - "line": 151, - "guard": null, - "pattern": "method, path, params_or_body", - "kind": "def", - "end_line": 154, - "ast_sha": "a34e6d69b6fcc46856ba1aba50c6e5b2aef8fb1b16295a55a602c4357c402877", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "05b989c814bef29a670f992e15770502064ed921ec163a077bc542af29b73a80", - "start_line": 151, - "name": "build_conn", - "arity": 3 - }, - "dispatch_endpoint/5:234": { - "line": 234, - "guard": "is_binary(path)", - "pattern": "conn, endpoint, method, path, params_or_body", - "kind": "defp", - "end_line": 237, - "ast_sha": "79d651952daf1b0bef18aa9dddd95aaae092db44c6ac80d9e20664f08185e26a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "f283b75d8359a1686204ed6d29b00a1fc10ca8af1c6563703400acdc8a176003", - "start_line": 234, - "name": "dispatch_endpoint", - "arity": 5 - }, - "redirected_params/1:590": { - "line": 590, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 590, - "ast_sha": "e41a95d0d2d9f7fd3281b9a37017c7b26d741ca78fa11f11bf3aae89a73eb6df", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "6331f6652fd69455a623e05ab625494872509bbed3c6d8b60887bd63f86b2c05", - "start_line": 590, - "name": "redirected_params", - "arity": 1 - }, - "redirected_to/2:453": { - "line": 453, - "guard": null, - "pattern": "conn, status", - "kind": "def", - "end_line": 454, - "ast_sha": "2428087f71914986ae61a89b24e0cfe91314b2974a353e505113a0bbecf9be96", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "dff4ac26fa938325f70eb349b8409ab67b5929bfcc84c15630bd2a9f58aa7330", - "start_line": 453, - "name": "redirected_to", - "arity": 2 - }, - "response/2:367": { - "line": 367, - "guard": null, - "pattern": "%Plug.Conn{status: status, resp_body: body}, given", - "kind": "def", - "end_line": 373, - "ast_sha": "ea0f9e9527684a6fdfb70f2d534ead2c81413265f90d2dc0a1f5955b57dad931", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "8e93c0d7e84753daff0c042a612d01ceed666e490bcc5b56f3c556f5da9f313a", - "start_line": 367, - "name": "response", - "arity": 2 - }, - "assert_error_sent/2:677": { - "line": 677, - "guard": null, - "pattern": "status_int_or_atom, func", - "kind": "def", - "end_line": 686, - "ast_sha": "672902839b6212675f55054b6864a8202a40702880dd459295720d47d49ca29e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "b6f06e175b634fd1acfe8df07845c47a7b55d42770d14a369b2552de7520c991", - "start_line": 677, - "name": "assert_error_sent", - "arity": 2 - }, - "json_response/2:418": { - "line": 418, - "guard": null, - "pattern": "conn, status", - "kind": "def", - "end_line": 422, - "ast_sha": "3da3a9c03189ed09afa68eb7255ca5c8d8bea84600d9b009fb85be5bee4ed75f", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "9e7e6cd5c20ac735b4ea80211d1afd2e022b5f240e1b620f42cb408bc25f773e", - "start_line": 418, - "name": "json_response", - "arity": 2 - }, - "build_conn/0:139": { - "line": 139, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 140, - "ast_sha": "df982030e955bfbd42afaee4910aa044748b8a3c3ca6ac021cf9aff149416364", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "7afc0de82194a551269b999229678d7046eb61addea7a341be2d2a9326b5a663", - "start_line": 139, - "name": "build_conn", - "arity": 0 - }, - "remove_script_name/3:603": { - "line": 603, - "guard": null, - "pattern": "conn, router, path", - "kind": "defp", - "end_line": 610, - "ast_sha": "6d9ddc3c8ec1e96bb56b84f25130537155c3b7bc11fbcff70026b6591f588f10", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "8ec6ff1eff0a389e93a2abb25f5ab0c00eabf6ecc074323fa378868d474c7fbd", - "start_line": 603, - "name": "remove_script_name", - "arity": 3 - }, - "bypass_through/3:572": { - "line": 572, - "guard": null, - "pattern": "conn, router, pipelines", - "kind": "def", - "end_line": 573, - "ast_sha": "7209434fd3993be5dd4e6dd234826772579b27bb45bc2946e2b1496bf7075496", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "7a50e9f4d5d3bb69c87376519055e1ac77c21bdada31a62626083695afb242c2", - "start_line": 572, - "name": "bypass_through", - "arity": 3 - }, - "receive_response/2:689": { - "line": 689, - "guard": null, - "pattern": "{:ok, conn}, expected_status", - "kind": "defp", - "end_line": 693, - "ast_sha": "b3176c12432ee3467a2543968eb7229f9107f65eb0c349a0bc31298d01975be9", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "dee345b1d903ebb77740139f6edcf4d1fec469fda7a086940549f01877b2e268", - "start_line": 689, - "name": "receive_response", - "arity": 2 - }, - "ensure_recycled/1:496": { - "line": 496, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 500, - "ast_sha": "b58388e2154c7042c95854ed2124228b075fc5d49fcea3ea858d4b0e4eed5afa", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c91d821de92003844682a328ebff906189cebe4809ad735853142de9486dc040", - "start_line": 496, - "name": "ensure_recycled", - "arity": 1 - }, - "post/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "b9fbd8b32626aaa1bfc2ce83a13bd7e588945351e47afb5051707eff3e726f25", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "post", - "arity": 2 - }, - "redirected_to/1:438": { - "line": 438, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 438, - "ast_sha": "09c4e56f659a52cf6619023051148f4dde87fe8414265d67eb36c3891a718b02", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "16fbf6ded5f6b33841c36ace7b0f95d50711a1093f4c28e5ed824dc1fac1788b", - "start_line": 438, - "name": "redirected_to", - "arity": 1 - }, - "discard_previously_sent/0:717": { - "line": 717, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 722, - "ast_sha": "992ff14de29814a12923368899964e863fd75ecd5fc6b76538b002e43440ba0a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "3deffad8fa1d3bd05f233468535967409dc5e3e870ed95b97a97560bbed5262e", - "start_line": 717, - "name": "discard_previously_sent", - "arity": 0 - }, - "bypass_through/2:562": { - "line": 562, - "guard": null, - "pattern": "conn, router", - "kind": "def", - "end_line": 563, - "ast_sha": "b1890afaa6654f47df7847e9e3352edc6a6d3733bc93123ceadedd1cdf3a1de8", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "5011004780881c6e4ee5efe85cad484b79004ed8d4ac682e0e9038b9e981dac2", - "start_line": 562, - "name": "bypass_through", - "arity": 2 - }, - "dispatch_endpoint/5:240": { - "line": 240, - "guard": "is_atom(action)", - "pattern": "conn, endpoint, method, action, params_or_body", - "kind": "defp", - "end_line": 243, - "ast_sha": "fc08eb02d2192ca7d43fdfeb9d416085f53a192caf0fd147284ad95949caccda", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "89f854d06f4b5a3edd49abe93d572a13cf186e381c6ceaa5e311bc7c43452943", - "start_line": 240, - "name": "dispatch_endpoint", - "arity": 5 - }, - "path_params/2:626": { - "line": 626, - "guard": "is_binary(to)", - "pattern": "%Plug.Conn{} = conn, to", - "kind": "def", - "end_line": 634, - "ast_sha": "7aa96d2fe9e6b4df8d6cc3d42274ce3aa8bde2b360851750e89daadc14859452", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "3cd914cfb73df5c2a8edd70b7a94aaf56be15a912e43be4a531abba473cad4a6", - "start_line": 626, - "name": "path_params", - "arity": 2 - }, - "response/2:357": { - "line": 357, - "guard": null, - "pattern": "%Plug.Conn{state: :unset}, _status", - "kind": "def", - "end_line": 358, - "ast_sha": "087fa9bfe00e13c184aea952ae2e6190d671d4c333b9c8a36e93f41c44d9bbee", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "776b864948251e7573e583d5b886941b3026be860d0fea31a20372d5c964dc2a", - "start_line": 357, - "name": "response", - "arity": 2 - }, - "put_flash/3:293": { - "line": 293, - "guard": null, - "pattern": "conn, key, value", - "kind": "def", - "end_line": 293, - "ast_sha": "0cc0d0e768353ec05ef8271d35cf425a2cae2c0cc2441c105763b3578b8dfd21", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "d1241bca377bd5908aa0098d4ab3a5d00921bfe761ff0d9d32e25a5c2652e4d2", - "start_line": 293, - "name": "put_flash", - "arity": 3 - }, - "head/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "900911b90a47ca57e041d0f0278092afd835f75a35f628195f56a4359d338e57", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "head", - "arity": 2 - }, - "delete_req_cookie/2:265": { - "line": 265, - "guard": null, - "pattern": "conn, key", - "kind": "def", - "end_line": 265, - "ast_sha": "ba2f663f7e9891c55c8c158dd7b9b320f751beb188f9fdf9c54860c0321373f1", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "883ba24a79b52d797d4d61660f2143dfe9e918362beca0f68451703cf7b273ec", - "start_line": 265, - "name": "delete_req_cookie", - "arity": 2 - }, - "recycle/1:476": { - "line": 476, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 476, - "ast_sha": "b2196471430cff8f5341f6f940093217dd5983b6a84c07b2eb64a1c9a76e99c0", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "956633e4ea0daf15d04337a2d47757e88c6744237fd518afcea0a9d4119108b0", - "start_line": 476, - "name": "recycle", - "arity": 1 - }, - "from_set_to_sent/1:246": { - "line": 246, - "guard": null, - "pattern": "%Plug.Conn{state: :set} = conn", - "kind": "defp", - "end_line": 246, - "ast_sha": "f36530cc3f368698810ed2457c3dd8cbb72a17f05d53d5ad67de135e042dd37f", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "32cdfe9535d07441e843cd7c2e445e66990b9380f0fe3f8fe17a9d6b14d5015f", - "start_line": 246, - "name": "from_set_to_sent", - "arity": 1 - }, - "from_set_to_sent/1:247": { - "line": 247, - "guard": null, - "pattern": "conn", - "kind": "defp", - "end_line": 247, - "ast_sha": "3788dcdb03297e0fc1a6cba16bc738d5200d64d9adf1d9a1d685c40a8e5a772e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c349254f30959dbc91231e7be27c8f7edefb0594e6014c00e55d2dcaec7e2041", - "start_line": 247, - "name": "from_set_to_sent", - "arity": 1 - }, - "get/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "0836d4eba6348894b50c21f418b6a7239af5ef6216dd028ce576db1aed130ddd", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "get", - "arity": 2 - }, - "fetch_flash/1:271": { - "line": 271, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 271, - "ast_sha": "590f1eafbde1a08cb81f0b83c3badacf6c7925d7702ae4596d4e3465a6c776db", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "7fb10f23f796d8eb8568cdd842e1822f113efaf74acc52b247a0c0cea704fd68", - "start_line": 271, - "name": "fetch_flash", - "arity": 1 - }, - "delete/2:165": { - "line": 165, - "guard": null, - "pattern": "x0, x1", - "kind": "defmacro", - "end_line": 165, - "ast_sha": "afd3ea3e7cf54a170e7e5c5ffa3da88f0be0d3fcd75f4414ff9670ed7ab28b0c", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a297eb686e64aa7bef42ac756381ab298599ab3fb53359aac622876ed0da8e3f", - "start_line": 165, - "name": "delete", - "arity": 2 - }, - "wrap_request/1:726": { - "line": 726, - "guard": null, - "pattern": "func", - "kind": "defp", - "end_line": 730, - "ast_sha": "ead6d5b6d3c82a1419ae8738573b02fba914d4fbcaaa56429c2b5ea648b73bfd", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a399bf47fb6e98906161ce632f7175595b11cd895dc8f94c994c70c5023086de", - "start_line": 726, - "name": "wrap_request", - "arity": 1 - }, - "head/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "a32cc12c340f81f30a6a43fde09034c0110edb5a2d10afce84e9264bd0ddc07a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "head", - "arity": 3 - }, - "redirected_to/2:448": { - "line": 448, - "guard": null, - "pattern": "%Plug.Conn{status: status} = conn, status", - "kind": "def", - "end_line": 450, - "ast_sha": "8610d780f599b3636eb11a6a5d2b4f65616e96a0e4dd8a16e7634bbefd403b0c", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "d1ae3a4ed63476af067967af12637c97faffc7e33c46016b32914387eaa71047", - "start_line": 448, - "name": "redirected_to", - "arity": 2 - }, - "delete/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "e6e83e96d96e88a1b5cd7e0ffa04d45dd7a3921c44ae676cec5e0b4e8880e986", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "delete", - "arity": 3 - }, - "build_conn/2:151": { - "line": 151, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 151, - "ast_sha": "859855eb91131699742d24fab4b72e052bdff5848f3ee04f3188ec50cdb3734a", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "6a25ff23aa1e2228d52f30000a43b44ea42778bbecad81c6c9d6162caa55ec01", - "start_line": 151, - "name": "build_conn", - "arity": 2 - }, - "post/3:165": { - "line": 165, - "guard": null, - "pattern": "conn, path_or_action, params_or_body", - "kind": "defmacro", - "end_line": 169, - "ast_sha": "163d1cb93c441eafa377f4c8031bb79b13c2a1c66c7c4b4df6f9ea4dd4e30c09", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "c0d77a8b2292cfb096e57f1c3d62c0598b83e9fc59d66c841e5ac6a563a3faf7", - "start_line": 165, - "name": "post", - "arity": 3 - }, - "bypass_through/1:552": { - "line": 552, - "guard": null, - "pattern": "conn", - "kind": "def", - "end_line": 553, - "ast_sha": "56eeb96838147dcab2914dd14766fcd189eaae3b851effd13382c9a9e70be010", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "e98c1a6d00ef37b05e20cadd7f2301a0f7fd5d14d795f151de189f0116fbc222", - "start_line": 552, - "name": "bypass_through", - "arity": 1 - }, - "response_content_type/2:311": { - "line": 311, - "guard": "is_atom(format)", - "pattern": "conn, format", - "kind": "def", - "end_line": 322, - "ast_sha": "6903f33c7f473c2a1e953888e7fdd986bdf8720775c398a76e7df890d7cb5c0b", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "a4c4c2882e49f971d5e1954afcff039c38370bc1046522876af9dac1a0d49841", - "start_line": 311, - "name": "response_content_type", - "arity": 2 - }, - "dispatch/5:213": { - "line": 213, - "guard": null, - "pattern": "%Plug.Conn{} = conn, endpoint, method, path_or_action, params_or_body", - "kind": "def", - "end_line": 227, - "ast_sha": "64137493c33df69d7b668a6417e88c4da7e99da5259db4dc08775a54569b240d", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "9dce62aa17c9dec56574b9eba86d54336d73467496e611a0dff956958f496bc2", - "start_line": 213, - "name": "dispatch", - "arity": 5 - }, - "dispatch/4:212": { - "line": 212, - "guard": null, - "pattern": "x0, x1, x2, x3", - "kind": "def", - "end_line": 212, - "ast_sha": "2ee3e0b32d5d8731143c61fc6b3668304b8e46ce3401485282a04e5bcd86c17e", - "source_file": "lib/phoenix/test/conn_test.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/test/conn_test.ex", - "source_sha": "5a1b97819c7a5cb46108b7e677a4fe6901e69906a7dbddcc085828161f038204", - "start_line": 212, - "name": "dispatch", - "arity": 4 - } - }, - "Mix.Tasks.Phx.Gen.Live": { - "context_files/1:205": { - "line": 205, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: true} = context", - "kind": "defp", - "end_line": 206, - "ast_sha": "5f2ea054a55c18bf6691946aee4cc547a71d9c92036791baa2f43daea35bb976", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", - "start_line": 205, - "name": "context_files", - "arity": 1 - }, - "context_files/1:209": { - "line": 209, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: false}", - "kind": "defp", - "end_line": 209, - "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", - "start_line": 209, - "name": "context_files", - "arity": 1 - }, - "copy_new_files/3:231": { - "line": 231, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", - "kind": "defp", - "end_line": 249, - "ast_sha": "ef458372fdc85f93b39ef098f57514add2bf4ec2c95bf1bf45e62bfb24119bef", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "7e321656048ee52e6b7becc0db32ab7ad8e497a999b2d2e1e488013e78c70008", - "start_line": 231, - "name": "copy_new_files", - "arity": 3 - }, - "default_options/1:423": { - "line": 423, - "guard": null, - "pattern": "{:array, :string}", - "kind": "defp", - "end_line": 424, - "ast_sha": "01549ffdfb83d7237a99f500b49ba21c9e00723d02db660bfa38d46a7648ff8f", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "f7baf8656ec69550ba797003cef4dbce49c50ef0b06cbbde34d1c7ec4a169d69", - "start_line": 423, - "name": "default_options", - "arity": 1 - }, - "default_options/1:426": { - "line": 426, - "guard": null, - "pattern": "{:array, :integer}", - "kind": "defp", - "end_line": 427, - "ast_sha": "ed3b02b5601a65b945fa5b81324b9a7cc04e437cd57b65d86235d1375131b558", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "0c6bc5b7c2583cc53321531782442ea51cc59459c6217490af281d5912293cc3", - "start_line": 426, - "name": "default_options", - "arity": 1 - }, - "default_options/1:429": { - "line": 429, - "guard": null, - "pattern": "{:array, _}", - "kind": "defp", - "end_line": 429, - "ast_sha": "5d58293c50e5eb42c1fc4cac63844c442b64a79f7acb29119153166f52272db3", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "71475429cbe803cbdb6e7877819a8eb755b00b60d50eb7ad2408348c028d0ed0", - "start_line": 429, - "name": "default_options", - "arity": 1 - }, - "do_inject_imports/4:268": { - "line": 268, - "guard": null, - "pattern": "context, file, file_path, inject", - "kind": "defp", - "end_line": 292, - "ast_sha": "bc49c06f149fcc7126cee6d33e6a79ca891495748c388452e481b405c0a2190a", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "3d35c7d82e3130216d8ac07044015a8941b5376dcc5c000c312c467de7fe1626", - "start_line": 268, - "name": "do_inject_imports", - "arity": 4 - }, - "files_to_be_generated/1:213": { - "line": 213, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", - "kind": "defp", - "end_line": 227, - "ast_sha": "47bc34bc7579a220d7f84945270bbb51d8741ea712576e8bfdcad2bd3db43fd7", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "1886d6dce8289e5b04b8bcdb13734db76d4382eca995f56c6d045d2470771ef0", - "start_line": 213, - "name": "files_to_be_generated", - "arity": 1 - }, - "inputs/1:362": { - "line": 362, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{} = schema", - "kind": "def", - "end_line": 419, - "ast_sha": "c0508df42c676b0d989bc346b291eeb3730dbf8fa66f15b7104cd11430c8d39f", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "16bf2a246cd580e79693583ef3182c772c4ed7b235e48bc392610554461f5a30", - "start_line": 362, - "name": "inputs", - "arity": 1 - }, - "label/1:431": { - "line": 431, - "guard": null, - "pattern": "key", - "kind": "defp", - "end_line": 431, - "ast_sha": "889b010b2220ae9186063009d2692c759aa9e861d5245e59485d14d5778faef0", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "a298472558e596e1e6ef15fbde1f3acc423119bdc3f18e26b72461c14e3fb8ac", - "start_line": 431, - "name": "label", - "arity": 1 - }, - "live_route_instructions/1:344": { - "line": 344, - "guard": null, - "pattern": "schema", - "kind": "defp", - "end_line": 357, - "ast_sha": "7ac87ecf56c783ca3b73b2ec7841eca84c4581c5ff22a77ada8d163bb71c94de", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "df86314d5fc4aed4008fd82ac57ab1fa13c70af17a8a0d2f85e6b5db829ea657", - "start_line": 344, - "name": "live_route_instructions", - "arity": 1 - }, - "maybe_inject_imports/1:252": { - "line": 252, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context", - "kind": "defp", - "end_line": 265, - "ast_sha": "893562d15a731f2e8e237bb565300eade49d4147d854407a7bd113f33457bf83", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "1b389cfb0fee2bb36dfc359c5b2354383c4ae6cec6478c2bb27e566a1a17bd9a", - "start_line": 252, - "name": "maybe_inject_imports", - "arity": 1 - }, - "maybe_print_upgrade_info/0:333": { - "line": 333, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 335, - "ast_sha": "f941d1e26061670ade00666c89adfc33b8656e08acb63827fa9e5781c99ad13b", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "29a2bd45c141787a57c4dac7965243266d2b0c8e857726fbe2cfa972020de7f8", - "start_line": 333, - "name": "maybe_print_upgrade_info", - "arity": 0 - }, - "print_shell_instructions/1:298": { - "line": 298, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", - "kind": "def", - "end_line": 330, - "ast_sha": "43e4c8bd46517a0de59197f62b97358d199dee7d4b9bf2222c2abd6cff717e6e", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "3e7fe3b9fd570b62c3c4a85bd720c07d5dfab1c4cdc6ed274d0d0682af2c4511", - "start_line": 298, - "name": "print_shell_instructions", - "arity": 1 - }, - "prompt_for_conflicts/1:198": { - "line": 198, - "guard": null, - "pattern": "context", - "kind": "defp", - "end_line": 202, - "ast_sha": "eed4c4b6928808d3b0ea8df4fd6fc5719a50afffc25b83062d346fa1085f214e", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "90bb78b802f638a452de361d55b4ad7f730fbc458b81fbed27efc49236a0c1d1", - "start_line": 198, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "run/1:125": { - "line": 125, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 183, - "ast_sha": "a0c4a9081924c67341013e75a40c4d3c630e683a5131bd2fb4f544d28130b4ac", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "6fb0c840fbb88d87dbf5c94c2bb3758a7a5f8b6dfaf8e278b00ab9c3d9002193", - "start_line": 125, - "name": "run", - "arity": 1 - }, - "scope_assign_route_prefix/1:445": { - "line": 445, - "guard": "not (route_prefix == nil)", - "pattern": "%{scope: %{route_prefix: route_prefix, assign_key: assign_key}} = schema", - "kind": "defp", - "end_line": 449, - "ast_sha": "8a88c4f9c977171ebf0cbd13a52843c55651c658d3077f2c9f62d6a7e9073dcb", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "247e983a0169c88f62cf9b99c16687f4771d0a3659a130b699eb8f10bd06326e", - "start_line": 445, - "name": "scope_assign_route_prefix", - "arity": 1 - }, - "scope_assign_route_prefix/1:452": { - "line": 452, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 452, - "ast_sha": "681880fcec3bd5d00863a548141d65a8bd8599f22c0da13e9af0baea93a2768c", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "e9a8e972479e20da74d9b8d9fdd7cc2007152cc11ee0fa7b7a4a1cc6cfadb0e4", - "start_line": 452, - "name": "scope_assign_route_prefix", - "arity": 1 - }, - "scope_param/1:433": { - "line": 433, - "guard": null, - "pattern": "%{scope: nil}", - "kind": "defp", - "end_line": 433, - "ast_sha": "0be4c98bc8c1e055676e5a164eaaacb027d03702091223bbf75a9e27f4aa8795", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "27adea72f54f4b0e00095bef7ae227bd9cfabe5f3009b12cf87ccadb4ed6e002", - "start_line": 433, - "name": "scope_param", - "arity": 1 - }, - "scope_param/1:435": { - "line": 435, - "guard": "not (route_prefix == nil)", - "pattern": "%{scope: %{route_prefix: route_prefix}}", - "kind": "defp", - "end_line": 435, - "ast_sha": "aa77a89cc1ef0f17c564b906a75bec4f9b509ef34c06db50210d8c0705529ee4", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "862bb69c196baa455ac9334092b391773ac8241a59e12a065ace2200d1536bc8", - "start_line": 435, - "name": "scope_param", - "arity": 1 - }, - "scope_param/1:438": { - "line": 438, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 438, - "ast_sha": "497083a97bb860901989df1d222da8cc59bf4c62eb142c3433474d9684adbfca", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "d1a1da2da764c388940eb0310d71b11cac2a5fd8fa4e31bb78ec0c586c06039d", - "start_line": 438, - "name": "scope_param", - "arity": 1 - }, - "scope_param_prefix/1:440": { - "line": 440, - "guard": null, - "pattern": "schema", - "kind": "defp", - "end_line": 442, - "ast_sha": "368a2faa97c5cc645a1751bd4c73ac483508e4bc3f413602df5d6a348e5e5ab1", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "e3b8234b7d2e03353273189b705d8ea379fc4d1bc6f310ecaeaa04def2c8a3fc", - "start_line": 440, - "name": "scope_param_prefix", - "arity": 1 - }, - "validate_context!/1:186": { - "line": 186, - "guard": null, - "pattern": "context", - "kind": "defp", - "end_line": 193, - "ast_sha": "c8d1e632ebbaba71dd69af9f4da61bb4069e07b89d116e5837ad797da4714d78", - "source_file": "lib/mix/tasks/phx.gen.live.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.live.ex", - "source_sha": "6e597180007873e0ebfd89192015eec3837a13876913600d6902f99323b85438", - "start_line": 186, - "name": "validate_context!", - "arity": 1 - } - }, - "Phoenix.Socket.Broadcast": { - "__struct__/0:84": { - "line": 84, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 84, - "ast_sha": "156adac11563e1a8f578a01d8a26fa032010a48c84b4d26c93143a00186e2738", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "b8bd420528f6722df63c2785b86107c2fb928254c8dae3cfbe76fe618d95f51f", - "start_line": 84, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:84": { - "line": 84, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 84, - "ast_sha": "775d883c8c56ecb795debc1e86a37715a620259650ac2cd75c0122b9534dcdd0", - "source_file": "lib/phoenix/socket/message.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/message.ex", - "source_sha": "b8bd420528f6722df63c2785b86107c2fb928254c8dae3cfbe76fe618d95f51f", - "start_line": 84, - "name": "__struct__", - "arity": 1 - } - }, - "Phoenix.Router.MalformedURIError": { - "__struct__/0:25": { - "line": 25, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 25, - "ast_sha": "1995670eccc62103070573c9956ac8bf5b66cad97d35b091c937cae2e4c1858b", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", - "start_line": 25, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:25": { - "line": 25, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 25, - "ast_sha": "78960ef9666aee750ea3e22daf0571a84be562627f5c880deb952d66f9df8297", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", - "start_line": 25, - "name": "__struct__", - "arity": 1 - }, - "exception/1:25": { - "line": 25, - "guard": "is_list(args)", - "pattern": "args", - "kind": "def", - "end_line": 25, - "ast_sha": "4b9ff8a2b73be1d8afbfa7e43d23622808281016f0ef3fa0e4c003e0a488b6c1", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", - "start_line": 25, - "name": "exception", - "arity": 1 - }, - "message/1:25": { - "line": 25, - "guard": null, - "pattern": "exception", - "kind": "def", - "end_line": 25, - "ast_sha": "707ecb09aaff0ee9cf0991ddad1f393af3d1429519d16aedb4a77cc182fb7637", - "source_file": "lib/phoenix/router.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router.ex", - "source_sha": "53daab11a776181d1cff9fe37f3239383b2a98630c47ad1d4dfea032a607e7fb", - "start_line": 25, - "name": "message", - "arity": 1 - } - }, - "Phoenix.Presence.Tracker": { - "child_spec/1:429": { - "line": 429, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 429, - "ast_sha": "dd8bad510a2c0064f75eb786c2e8dcef2350096f03f38b5c13bd2be76e7787f1", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "7c2592ee4bdddc1bef6cded482f11ff7073499e053972177ce3cb4b40acf8709", - "start_line": 429, - "name": "child_spec", - "arity": 1 - }, - "handle_diff/2:446": { - "line": 446, - "guard": null, - "pattern": "diff, state", - "kind": "def", - "end_line": 446, - "ast_sha": "29bbc10541053251eeb0801e793c9f08e045d5ca2857a38874c3fe3e4a9455ae", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "11391e4cedab663bc63eeef18881db4a75b61aab534e1e8a57a280db5fc83f2d", - "start_line": 446, - "name": "handle_diff", - "arity": 2 - }, - "handle_info/2:448": { - "line": 448, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 449, - "ast_sha": "1e971145cf281f0672c4653cd8ff9881790479a129e4120535b9d71c06e2d506", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "d8a0aa9c36017f3f1e5d1edb99722b00ba766ffddb87aac114d4311f1d3a95e0", - "start_line": 448, - "name": "handle_info", - "arity": 2 - }, - "init/1:444": { - "line": 444, - "guard": null, - "pattern": "state", - "kind": "def", - "end_line": 444, - "ast_sha": "7a36a23f05cedbcf26bb944bf48aa0ce6c8c97b26c181da656dfa546b23eba60", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "a6d1863ed96cdab255c9006443eb22e75783101ad94fb44e263147efbff70712", - "start_line": 444, - "name": "init", - "arity": 1 - }, - "start_link/1:431": { - "line": 431, - "guard": null, - "pattern": "{module, task_supervisor, opts}", - "kind": "def", - "end_line": 440, - "ast_sha": "113c212c16be2e0e4355d4a0a7dfd25bcc505e945df6300fb9bd7138549284d5", - "source_file": "lib/phoenix/presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/presence.ex", - "source_sha": "4ffd914f52b257c23d675e72fcfe2f56800751718d0761231195416196816945", - "start_line": 431, - "name": "start_link", - "arity": 1 - } - }, - "Phoenix.Transports.WebSocket": { - "call/2:39": { - "line": 39, - "guard": null, - "pattern": "%{method: \"GET\"} = conn, {endpoint, handler, opts}", - "kind": "def", - "end_line": 90, - "ast_sha": "0a15e260925731abb5ce90f85e455c8a6a316609c4aec968567bda6902688a27", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "827630ef1271620693c5a30b33a1c42654160facaa7b9346f812533590b091c9", - "start_line": 39, - "name": "call", - "arity": 2 - }, - "call/2:95": { - "line": 95, - "guard": null, - "pattern": "conn, _", - "kind": "def", - "end_line": 95, - "ast_sha": "6a270d60667739174b1e69d7ac7189ae374deee047bcec0ebb914c355d279ed6", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "92126c569a2587d2a9f84ded3a5b68fcbf66713bacaa03e9e93ac68884fccaf8", - "start_line": 95, - "name": "call", - "arity": 2 - }, - "default_config/0:26": { - "line": 26, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 30, - "ast_sha": "83052cd1c678de25649b63ac27aba74840220e65d65e019fadcaac5d5a2a4e19", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "3c9bfe7919906cbd660ccd0ded6185b8e16a1a87c6dabffcb420a6a4cd6e572d", - "start_line": 26, - "name": "default_config", - "arity": 0 - }, - "handle_error/2:97": { - "line": 97, - "guard": null, - "pattern": "conn, _reason", - "kind": "def", - "end_line": 97, - "ast_sha": "9d1681ce259b6a5cbb150f58a5264cf52b5c4136f750c3540699f45685ece77e", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "fa5cba5745f812200aac32656c95c4c47bab21b037c96f41ee0a3f347890a346", - "start_line": 97, - "name": "handle_error", - "arity": 2 - }, - "init/1:37": { - "line": 37, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 37, - "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", - "start_line": 37, - "name": "init", - "arity": 1 - }, - "maybe_auth_token_from_header/2:124": { - "line": 124, - "guard": null, - "pattern": "conn, _", - "kind": "defp", - "end_line": 124, - "ast_sha": "d418dff67505cf526abe380616091b9f20a1537b40a9770ff5b9292092c7c786", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "3465c5df608942102ca5a8d5c47d36aefaa005f81aec552c3d646fd73d7b2083", - "start_line": 124, - "name": "maybe_auth_token_from_header", - "arity": 2 - }, - "maybe_auth_token_from_header/2:99": { - "line": 99, - "guard": null, - "pattern": "conn, true", - "kind": "defp", - "end_line": 119, - "ast_sha": "ccc15490e332cb39f21dbdf9b6a7ab974ff0ab2aa146cf0dbde9414a60594fc2", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "f17cead75132a04ead67742ae47efd76a42ffa336f84ea619de4b40a84d52f6a", - "start_line": 99, - "name": "maybe_auth_token_from_header", - "arity": 2 - }, - "set_actual_subprotocols/2:126": { - "line": 126, - "guard": null, - "pattern": "conn, []", - "kind": "defp", - "end_line": 126, - "ast_sha": "fb0b120244e528cf45ff61ee9d3985833c2ecba61f0a1b9a95a02dc13c117d56", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "6208875b938e8f18095ea00efc2beab293839cf73a585d5b9607ec4c159f0d56", - "start_line": 126, - "name": "set_actual_subprotocols", - "arity": 2 - }, - "set_actual_subprotocols/2:128": { - "line": 128, - "guard": null, - "pattern": "conn, subprotocols", - "kind": "defp", - "end_line": 129, - "ast_sha": "2ab885da31271956d17e500cd1acef636a5c26beb24a97cc194ab84c4a336187", - "source_file": "lib/phoenix/transports/websocket.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/transports/websocket.ex", - "source_sha": "8ec5f911f96d10bd8de0cd08455a3a228eab2c74c88fdd0153faf3e17bbe9dad", - "start_line": 128, - "name": "set_actual_subprotocols", - "arity": 2 - } - }, - "Phoenix.Router.ConsoleFormatter": { - "calculate_column_widths/3:77": { - "line": 77, - "guard": null, - "pattern": "router, routes, endpoint", - "kind": "defp", - "end_line": 100, - "ast_sha": "aec1da2c1b6748fe59c5f21c929df28231eaf7b6ecc392b81088dfd08128b854", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "2f43d0506fc25a16c6c13e23ef58f23067914540caa574efe479545bb0f5d1e5", - "start_line": 77, - "name": "calculate_column_widths", - "arity": 3 - }, - "format/1:12": { - "line": 12, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 12, - "ast_sha": "5af33b378f1f21a99ac116d91626253061a0e6ba95e39831050e57a436339612", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "70396ac6ba0a2122ba78b616f9c9ec55489ec5f930a955099e25cbca78413784", - "start_line": 12, - "name": "format", - "arity": 1 - }, - "format/2:12": { - "line": 12, - "guard": null, - "pattern": "router, endpoint", - "kind": "def", - "end_line": 19, - "ast_sha": "090087836f4eb40e4107331afca6df08e4d1d6cf6747bab27c9a73037ae11657", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "eb2232582c0e7e89dbd37311d4f5e368f7e6c8f3de4d53e1c8e072cd2b6e557b", - "start_line": 12, - "name": "format", - "arity": 2 - }, - "format_endpoint/2:23": { - "line": 23, - "guard": null, - "pattern": "nil, _router", - "kind": "defp", - "end_line": 23, - "ast_sha": "8408127f0731978d264d59589cdd10837665f4be0dfa5c1483b585b17e9440a8", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "40ad14e36e58e60336ba16ee991bef6683d6847ed8d2f33552dc6a13ef0b6e63", - "start_line": 23, - "name": "format_endpoint", - "arity": 2 - }, - "format_endpoint/2:25": { - "line": 25, - "guard": null, - "pattern": "endpoint, widths", - "kind": "defp", - "end_line": 32, - "ast_sha": "8b4a7700b74d1e588dbe5a9a68de53b1293ce39d97ad9ea207ed29029000c6b5", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "53c67f2399dd6f80124abf777d72e29fbbc0cafaa5fe02d9e7b8553d0f01d226", - "start_line": 25, - "name": "format_endpoint", - "arity": 2 - }, - "format_longpoll/2:56": { - "line": 56, - "guard": null, - "pattern": "{_path, Phoenix.LiveReloader.Socket, _opts}, _", - "kind": "defp", - "end_line": 56, - "ast_sha": "face257af3ebbc42e806ad0770ff8f34342ab8228c9d189390700deff2d6c13a", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "d737e11b6662c1aed161c252c26b846dedc5c90d60f982c56281b30a35528157", - "start_line": 56, - "name": "format_longpoll", - "arity": 2 - }, - "format_longpoll/2:58": { - "line": 58, - "guard": null, - "pattern": "{path, module, opts}, widths", - "kind": "defp", - "end_line": 69, - "ast_sha": "2a2beb6495878cf35ac12240c2c33cef438e6c6833672163ea97ddaaf53775fa", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "4d3a1903371d9d9883342b3bcb5a0463cbb6c178af43d91771dc5e0dea65a338", - "start_line": 58, - "name": "format_longpoll", - "arity": 2 - }, - "format_route/3:104": { - "line": 104, - "guard": null, - "pattern": "route, router, column_widths", - "kind": "defp", - "end_line": 121, - "ast_sha": "b09742e4a69f5e9d04b850079014283abcb573d36b7fbd90d373e20914a845ed", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "7638108e96505b4ff9ff42c662890b7a4b5eef4a83556bcae2205754222d867d", - "start_line": 104, - "name": "format_route", - "arity": 3 - }, - "format_websocket/2:37": { - "line": 37, - "guard": null, - "pattern": "{_path, Phoenix.LiveReloader.Socket, _opts}, _", - "kind": "defp", - "end_line": 37, - "ast_sha": "face257af3ebbc42e806ad0770ff8f34342ab8228c9d189390700deff2d6c13a", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "c8df5492218d801aa9d23cddea0d467050e992dc6ab3eb50c10692555b557e49", - "start_line": 37, - "name": "format_websocket", - "arity": 2 - }, - "format_websocket/2:39": { - "line": 39, - "guard": null, - "pattern": "{path, module, opts}, widths", - "kind": "defp", - "end_line": 49, - "ast_sha": "0274c297479c3e3bef168059823e5e36b4b771182e1e910e5ec2178caac827fd", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "bf71d7f2545206d788fd7f3ad01cac7bb4f5289b56cf811cd9992072b2a6d9c6", - "start_line": 39, - "name": "format_websocket", - "arity": 2 - }, - "route_name/2:124": { - "line": 124, - "guard": null, - "pattern": "_router, nil", - "kind": "defp", - "end_line": 124, - "ast_sha": "60abc151cae31791e25de9995207ac349d4ae572866d128be3356466394a3f70", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "0a7ac060514ce09d9ce4c4009da71f864bc72056d03f66b4f9865b57a59ac1d8", - "start_line": 124, - "name": "route_name", - "arity": 2 - }, - "route_name/2:126": { - "line": 126, - "guard": null, - "pattern": "router, name", - "kind": "defp", - "end_line": 128, - "ast_sha": "06c8031304f8ccf793bffab7a61e7077598f1e9277893ecfa0cdc0585c646369", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "09cf474f92fd938acde9f17c4812bcdca471434914d8561575a354535b472cf5", - "start_line": 126, - "name": "route_name", - "arity": 2 - }, - "socket_verbs/1:136": { - "line": 136, - "guard": null, - "pattern": "socket_opts", - "kind": "defp", - "end_line": 138, - "ast_sha": "e2a37f4a18bd0010d59c53a7b3212ba0bf59276a2435135fde7f872be92ee378", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "603bbf52e30f5b6f80c3042c68d0440ce8c04bad4ba8d000d252f27195a875a0", - "start_line": 136, - "name": "socket_verbs", - "arity": 1 - }, - "verb_name/1:134": { - "line": 134, - "guard": null, - "pattern": "verb", - "kind": "defp", - "end_line": 134, - "ast_sha": "c68e9299fbe0a332ddba555cf27404f278bdbd3789ac7d6a293fde6117b6fd61", - "source_file": "lib/phoenix/router/console_formatter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/console_formatter.ex", - "source_sha": "b239d199b3f59562bcab913f0a6d5146da196417e3ab1dce971a015418f74134", - "start_line": 134, - "name": "verb_name", - "arity": 1 - } - }, - "Mix.Tasks.Compile.Phoenix": { - "mix_recompile?/1:50": { - "line": 50, - "guard": null, - "pattern": "_mod", - "kind": "defp", - "end_line": 50, - "ast_sha": "e20ff36bc6ae5df7fcd9a1f2ed37aa52443b52baa566570f40e65f26faed982f", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "811f47d371c7816b4abd68bd5406a908daea722fad36abc24dd9838b37185a56", - "start_line": 50, - "name": "mix_recompile?", - "arity": 1 - }, - "modules_for_recompilation/1:38": { - "line": 38, - "guard": null, - "pattern": "modules", - "kind": "defp", - "end_line": 40, - "ast_sha": "e7870f4941654f6f092da4da00f7ef1b7236dfe08ee645d7f00ceb4d0ad6347e", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "9b0ae2e369c0e835c66720c844b795122b4002fd6a89bad2b858327148821205", - "start_line": 38, - "name": "modules_for_recompilation", - "arity": 1 - }, - "modules_to_file_paths/1:57": { - "line": 57, - "guard": null, - "pattern": "modules", - "kind": "defp", - "end_line": 58, - "ast_sha": "cd1666fd661e68e3add2a11aab7bcf165326be395095b29c5b5013080b75b3c1", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "915440c11b29165b78fbf4bb3dd63d8e0ee9481cc72afe75a70a520acf26d2ed", - "start_line": 57, - "name": "modules_to_file_paths", - "arity": 1 - }, - "phoenix_recompile?/1:44": { - "line": 44, - "guard": null, - "pattern": "mod", - "kind": "defp", - "end_line": 45, - "ast_sha": "8c8703096ef346e9c3909f2508d70870922cd8cbf95d514e3127dde3f5bf4cf3", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "97a58d04e700c3f41957eb4e32760c591a96b89b0def263bd518a207347a839d", - "start_line": 44, - "name": "phoenix_recompile?", - "arity": 1 - }, - "run/1:7": { - "line": 7, - "guard": null, - "pattern": "_args", - "kind": "def", - "end_line": 20, - "ast_sha": "2cee42aa2fdbf0088dbeef1810a6d64a458e2249683db65696e4f0a1b84ab533", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "40d0eebfc7cc617d8811a9fdfa744b571810cd4c5a024301897fbc39d3ebc76a", - "start_line": 7, - "name": "run", - "arity": 1 - }, - "touch/0:25": { - "line": 25, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 31, - "ast_sha": "9e6b026c5ecbad5f7b484befc838b2c849a27969467a0dde9e0761dfcb255ce3", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "316426f471654ddb35ddb509c588d512eef4cb0601bdc7383396765101d3adb1", - "start_line": 25, - "name": "touch", - "arity": 0 - }, - "touch_if_exists/1:34": { - "line": 34, - "guard": null, - "pattern": "path", - "kind": "defp", - "end_line": 35, - "ast_sha": "69e3feb9701a886bf45aac2a010be95b5d9af59df8a02845d4497676c70bd637", - "source_file": "lib/mix/tasks/compile.phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/compile.phoenix.ex", - "source_sha": "39cd1cf2ec483f90a507e1ad2bad520b3bacd759acefa589bf18716affcb55df", - "start_line": 34, - "name": "touch_if_exists", - "arity": 1 - } - }, - "Phoenix.Socket.PoolSupervisor": { - "init/1:47": { - "line": 47, - "guard": null, - "pattern": "{endpoint, name, partitions}", - "kind": "def", - "end_line": 62, - "ast_sha": "2eccc13dd2d0f794d84364366a195b60aa038dc7bca368d9cecf51e942127aee", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "7c768896594767c13a01bc0b0f75667fb465853fd5b19e0f08ca0ce89b6ea509", - "start_line": 47, - "name": "init", - "arity": 1 - }, - "start_child/3:13": { - "line": 13, - "guard": null, - "pattern": "socket, key, spec", - "kind": "def", - "end_line": 28, - "ast_sha": "344efca6c6807486464459777bfc8559b213d005a26170697c2375c8e3de7ee2", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "1c5de7f797c0791bfb8d9729c963a0c6069ac54c3f2fd87ef356906c97962eb3", - "start_line": 13, - "name": "start_child", - "arity": 3 - }, - "start_link/1:5": { - "line": 5, - "guard": null, - "pattern": "{endpoint, name, partitions}", - "kind": "def", - "end_line": 9, - "ast_sha": "48e1287a703e08a9153182f7f54d2d8cb0fd38063313d2af3c3b20a6a79b8f57", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "807528c15450b22deb1f4e0626bb2faea75d8563f79b68f775a6ca5e479cef91", - "start_line": 5, - "name": "start_link", - "arity": 1 - }, - "start_pooled/2:35": { - "line": 35, - "guard": null, - "pattern": "ref, i", - "kind": "def", - "end_line": 42, - "ast_sha": "1546691fe11f3b629eceacd2ffec3115a41455b125428f358f4969257a9da234", - "source_file": "lib/phoenix/socket/pool_supervisor.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/socket/pool_supervisor.ex", - "source_sha": "6e2f6ec62959fbd39dee234f03caa17e80d89f06cd942d544e75cbbded16d9c0", - "start_line": 35, - "name": "start_pooled", - "arity": 2 - } - }, - "Phoenix.Endpoint.Cowboy2Adapter": { - "bound_address/2:124": { - "line": 124, - "guard": null, - "pattern": "scheme, ref", - "kind": "defp", - "end_line": 133, - "ast_sha": "255310bb4df745862fff94de63f3e6718d641f093eb85a805c51810797106487", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "453a675260f9e3d6fb046a68a0d0008eb8c6afb8a98a085e44486351bb7327d6", - "start_line": 124, - "name": "bound_address", - "arity": 2 - }, - "child_spec/4:78": { - "line": 78, - "guard": null, - "pattern": "scheme, endpoint, config, code_reloader?", - "kind": "defp", - "end_line": 94, - "ast_sha": "b8750c336fd5e28e19a551ebd16236503967bb51ef49b832bcc5d46f880259d2", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "c9c206fd22b0d6006573838c7c1f77c42cdbe8bc670174f5570acf65ab40d945", - "start_line": 78, - "name": "child_spec", - "arity": 4 - }, - "child_specs/2:52": { - "line": 52, - "guard": null, - "pattern": "endpoint, config", - "kind": "def", - "end_line": 74, - "ast_sha": "78253e80169b5989c553d98634f4616394852bf75840cc482d32dd2142d1c677", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "225074ee7a0da3b2132b26401c093bac23b5912193b18486e06910f419a11f95", - "start_line": 52, - "name": "child_specs", - "arity": 2 - }, - "info/3:119": { - "line": 119, - "guard": null, - "pattern": "scheme, endpoint, ref", - "kind": "defp", - "end_line": 121, - "ast_sha": "4b8c0268606d670655152de350f19b11968e65041ba8c4e18614a10c669e205e", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "feab93e109ef16cd5c05e4b00dc85b413f63ab43db5e465e705dafe5814d87b5", - "start_line": 119, - "name": "info", - "arity": 3 - }, - "make_ref/2:152": { - "line": 152, - "guard": null, - "pattern": "endpoint, scheme", - "kind": "defp", - "end_line": 153, - "ast_sha": "79bc3643c7fd8dd4d706aa450d2740e237297686222f8cc5a47bd58403532c65", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "fb193c09b79d7d823be1b1955985e330897dcf4f178e2aefa4909c7f04e84b8b", - "start_line": 152, - "name": "make_ref", - "arity": 2 - }, - "port_to_integer/1:137": { - "line": 137, - "guard": null, - "pattern": "{:system, env_var}", - "kind": "defp", - "end_line": 137, - "ast_sha": "56256b11f3e682bb249a1b10fbfe8a3ba26c3de02162d251d830016cdb9607bf", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "e3b91863e72be67bb9de16a0e26ee4de2d7463cc3e0d6b7c8756591f0b7fe557", - "start_line": 137, - "name": "port_to_integer", - "arity": 1 - }, - "port_to_integer/1:138": { - "line": 138, - "guard": "is_binary(port)", - "pattern": "port", - "kind": "defp", - "end_line": 138, - "ast_sha": "59f40fcfaab0be4d79d4c1262798dbadf3a66b838f129ad50b3d4b67eb9b6062", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "506fdff094b92b11c5e6bdcbb576f85d8a5503d1d0084c38d965017cec596895", - "start_line": 138, - "name": "port_to_integer", - "arity": 1 - }, - "port_to_integer/1:139": { - "line": 139, - "guard": "is_integer(port)", - "pattern": "port", - "kind": "defp", - "end_line": 139, - "ast_sha": "cad919fd626581b0483f841c270b6d53496d670660994359c8a795e10ec403e8", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "074f5f04a25e914d778ae0d21b26d1a362468488bf8979abbc0bab9ad5878c46", - "start_line": 139, - "name": "port_to_integer", - "arity": 1 - }, - "server_info/2:141": { - "line": 141, - "guard": null, - "pattern": "endpoint, scheme", - "kind": "def", - "end_line": 149, - "ast_sha": "380e78a30a2c429140329237c35331ec45cecf3c89488fee75b04a6fead9629d", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "0f48bb659398cc7ba7bc0dbe9c8d106f005f58ba8f20a9b46e4f7f60384c702d", - "start_line": 141, - "name": "server_info", - "arity": 2 - }, - "start_link/3:98": { - "line": 98, - "guard": null, - "pattern": "scheme, endpoint, {m, f, [ref | _] = a}", - "kind": "def", - "end_line": 115, - "ast_sha": "ee44f569956f7afaaedc65f424901da5ff54b72eb61a07cb400f8ea7391cc1d2", - "source_file": "lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/endpoint/cowboy2_adapter.ex", - "source_sha": "029e1b82d5f7d2066becfe5979dbe10dcd6e946296d7df620c79a3170660b4ed", - "start_line": 98, - "name": "start_link", - "arity": 3 - } - }, - "Phoenix.Config": { - "cache/3:47": { - "line": 47, - "guard": null, - "pattern": "module, key, fun", - "kind": "def", - "end_line": 70, - "ast_sha": "4ae0a15b366b42172fab73dcb0f3dfdaeab6dfbe599046541a5d6ffc28f2170f", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "a28135ff0dac401645803316f449984b2d77cc220b0d6a99ba7158bd7e933e3f", - "start_line": 47, - "name": "cache", - "arity": 3 - }, - "child_spec/1:9": { - "line": 9, - "guard": null, - "pattern": "init_arg", - "kind": "def", - "end_line": 862, - "ast_sha": "baca25a2936ae666e1588466e4be9983f98391425239c1c34af22dae49d3fda0", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", - "start_line": 9, - "name": "child_spec", - "arity": 1 - }, - "clear_cache/1:79": { - "line": 79, - "guard": null, - "pattern": "module", - "kind": "def", - "end_line": 80, - "ast_sha": "f62a681e6eedeb02c004f34e58d5245bdfbbbe6c0d071da7733357286fa8c53c", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "8b7968d783f9090eaf2d7f9aeeb06bf75f17d48ffca6c3d6e9637f772683b21b", - "start_line": 79, - "name": "clear_cache", - "arity": 1 - }, - "code_change/3:9": { - "line": 9, - "guard": null, - "pattern": "_old, state, _extra", - "kind": "def", - "end_line": 940, - "ast_sha": "6f43db8dcfc2348dd99e35de3d9b626db1e4f2b2e1508261dd9a587463c230cb", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", - "start_line": 9, - "name": "code_change", - "arity": 3 - }, - "config_change/3:125": { - "line": 125, - "guard": null, - "pattern": "module, changed, removed", - "kind": "def", - "end_line": 127, - "ast_sha": "dbb5b06cb65da1cfcc2ed48bd4cd7da2fe783b90897419116e0311e709e238ba", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "d8b4a603baa3686ab3d5059bdaa2ae97ca272d3627595c63bca0b5f492cd016e", - "start_line": 125, - "name": "config_change", - "arity": 3 - }, - "fetch_config/2:95": { - "line": 95, - "guard": null, - "pattern": "otp_app, module", - "kind": "defp", - "end_line": 98, - "ast_sha": "e555df1e55141495ea9d4308624f0a4188cc25cf1eb362a5ca09a589540ffe16", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "e0e0af8b771298afbc8d518e28d7605e691f4e63071046cf55833ee957cc7c7b", - "start_line": 95, - "name": "fetch_config", - "arity": 2 - }, - "from_env/3:89": { - "line": 89, - "guard": null, - "pattern": "otp_app, module, defaults", - "kind": "def", - "end_line": 92, - "ast_sha": "c799eafbacaae207f1bac2e7d6f1d854c94e0e79d6800136babcbde2651c8d7a", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "b6b1d74f2db1b482e6d4515e56d072a22f1fe910343e544209fd2a17163adc47", - "start_line": 89, - "name": "from_env", - "arity": 3 - }, - "handle_call/3:139": { - "line": 139, - "guard": null, - "pattern": "{:permanent, key, value}, _from, {module, permanent}", - "kind": "def", - "end_line": 141, - "ast_sha": "d65edab8003fd9cfba645c009d499fa4d05e8c6dc156a1892613e9dfbd72e9fd", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "365eb856b4d2df908a61a1879dfa4ab27d6a8df34d88b537c8d7978a42b65e0c", - "start_line": 139, - "name": "handle_call", - "arity": 3 - }, - "handle_call/3:144": { - "line": 144, - "guard": null, - "pattern": "{:config_change, changed, removed}, _from, {module, permanent}", - "kind": "def", - "end_line": 155, - "ast_sha": "f7e1ac8b242a061a4c39aa0cc2335e81182048d1d8f8a95e8bb8751771931a8a", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "7c6520cdd464e23c67bbf328d5299157c9d2631cfe08b3a324b2713afa204375", - "start_line": 144, - "name": "handle_call", - "arity": 3 - }, - "handle_cast/2:9": { - "line": 9, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 929, - "ast_sha": "24d661daf83bfa0b7c0d5c8dc4b4ed91cd5a6a654ce23978d9399dfa255b1c0b", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", - "start_line": 9, - "name": "handle_cast", - "arity": 2 - }, - "handle_info/2:9": { - "line": 9, - "guard": null, - "pattern": "msg, state", - "kind": "def", - "end_line": 912, - "ast_sha": "9c213083de9b6ab3f0679b07483924f7b187f2d0f2b0dae897415a75953f4d28", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "4931874385a62ac8ab1917b5ccde7a2bc7406232b947cab12da26f4b9915ce79", - "start_line": 9, - "name": "handle_info", - "arity": 2 - }, - "init/1:132": { - "line": 132, - "guard": null, - "pattern": "{module, config, permanent}", - "kind": "def", - "end_line": 136, - "ast_sha": "8ac7eef74b3b3ed348c189690d5cbda6b0a024a287c60d2be00a5658f1f0d472", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "69fbcbf7eac502ba5f7a63d156ad1bc9e5b986fa54aeeabf3e1c44ccb41d06d2", - "start_line": 132, - "name": "init", - "arity": 1 - }, - "merge/2:107": { - "line": 107, - "guard": null, - "pattern": "a, b", - "kind": "def", - "end_line": 107, - "ast_sha": "4984be24b24549bfaef520fc7082d24a8efcf845da01b5e89e7ae07067f060a2", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "ef77f12058cdb0519534e19d6935d056be80dd6e20859a30b8870b991f1b2b16", - "start_line": 107, - "name": "merge", - "arity": 2 - }, - "merger/3:109": { - "line": 109, - "guard": null, - "pattern": "_k, v1, v2", - "kind": "defp", - "end_line": 113, - "ast_sha": "eecd488011b611aa57f27d0bd994653448b2af6dd1e87cfe50a1cc004cc8d874", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "4033a289590825017d910a431c58b2d9c8d105a294f4c029e575c00a7c70fbc3", - "start_line": 109, - "name": "merger", - "arity": 3 - }, - "permanent/3:31": { - "line": 31, - "guard": null, - "pattern": "module, key, value", - "kind": "def", - "end_line": 33, - "ast_sha": "7691502b07f0feba884226086f779ec33f99831e286e503b75b0386e6cb140a8", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "1c7dac28d112ed47850aea1142633c1fa38a5657597d4bbd19cdab3035ebc90d", - "start_line": 31, - "name": "permanent", - "arity": 3 - }, - "put/3:22": { - "line": 22, - "guard": null, - "pattern": "module, key, value", - "kind": "def", - "end_line": 23, - "ast_sha": "de8a33b251daeb68279201cbb58bbf8f0e90a0c1f8a35f1e99daaba5a59c2fce", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "ad999f365b8ef9d2ee1a78ac8e6d63aa0a7207c760c47a0e969ba43627341639", - "start_line": 22, - "name": "put", - "arity": 3 - }, - "start_link/1:14": { - "line": 14, - "guard": null, - "pattern": "{module, config, defaults, opts}", - "kind": "def", - "end_line": 16, - "ast_sha": "009aa6cfde605c5fb8a23b03420b6b2ac186e227a5d577bf3b6c3a08efd01755", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "50b0bdfd8ab7f8816e38a0e478f45b9e6520132aab0e3cf360f1eec9973b6e48", - "start_line": 14, - "name": "start_link", - "arity": 1 - }, - "terminate/2:9": { - "line": 9, - "guard": null, - "pattern": "_reason, _state", - "kind": "def", - "end_line": 9, - "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", - "start_line": 9, - "name": "terminate", - "arity": 2 - }, - "update/3:159": { - "line": 159, - "guard": null, - "pattern": "module, config, permanent", - "kind": "defp", - "end_line": 164, - "ast_sha": "5133593182d5ee60090590d5d10ba79ea7772cbfd2108be313dc04f23ac09509", - "source_file": "lib/phoenix/config.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/config.ex", - "source_sha": "152ceaef6ea831b0e25eac6cacef66d8974a6c8fb0bd173949306f63e4788905", - "start_line": 159, - "name": "update", - "arity": 3 - } - }, - "Phoenix.Digester": { - "clean/3:335": { - "line": 335, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 335, - "ast_sha": "0c1328aac1bb2e7f32612dcc651603dc49c89768b123f060ae2226a7ac6fc0db", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "67f6c4a3c899cb544971d5c3fa74bc235d56ac225073525be2db4a093c2a1720", - "start_line": 335, - "name": "clean", - "arity": 3 - }, - "remove_compressed_files/2:407": { - "line": 407, - "guard": null, - "pattern": "files, output_path", - "kind": "defp", - "end_line": 408, - "ast_sha": "f043e0e18f446eb876f10822e2d06198b839905a4ec42fee1bfaa1e2ed23c4a1", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "c8fb1951f0ffa96efeb39e3bc1f995e391c3a0a99e020f6670bf651d4e6074d7", - "start_line": 407, - "name": "remove_compressed_files", - "arity": 2 - }, - "load_manifest/1:87": { - "line": 87, - "guard": null, - "pattern": "output_path", - "kind": "defp", - "end_line": 96, - "ast_sha": "4760bc3b46bfb51a610bd61917724fb5bb7fdbc66c51a27b6969a4e57f4d9877", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "6c1c505408797ae6c5fe303e8d50c13c08a10c0587e9176a647cd8c9cff2f7c3", - "start_line": 87, - "name": "load_manifest", - "arity": 1 - }, - "relative_digested_path/1:311": { - "line": 311, - "guard": null, - "pattern": "digested_path", - "kind": "defp", - "end_line": 312, - "ast_sha": "b1b2c29b9c37ee550dbf942caa28a7dbda4e39e3def5f76b139355714460391b", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "71d2f933496549c4521d5484a01f9cbb507b8390671b872093c41dcd859ee464", - "start_line": 311, - "name": "relative_digested_path", - "arity": 1 - }, - "now/0:9": { - "line": 9, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 10, - "ast_sha": "a426216498e6b24c3d6a23c4f6597027abcf5deac7a14c40478e0f26009bb3b3", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "f33b643ca894a657098ca15f0038929f5ac19e06df9c7927e4de60ffa1c3a1d2", - "start_line": 9, - "name": "now", - "arity": 0 - }, - "files_to_clean/4:376": { - "line": 376, - "guard": null, - "pattern": "latest, digests, max_age, keep", - "kind": "defp", - "end_line": 381, - "ast_sha": "f93dde3b33b316e116ef03234aabb10f6632608027ff515245f6086ac6f2e22a", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "27b1c2a900ffcb02f43bf5ded7fd16969b07a44872172dbf3f16ad9912bdb284", - "start_line": 376, - "name": "files_to_clean", - "arity": 4 - }, - "clean/4:335": { - "line": 335, - "guard": null, - "pattern": "path, age, keep, now", - "kind": "def", - "end_line": 340, - "ast_sha": "91ecea3a056b18698f86e2ea3d47ce7a1c0e4ae451142a4d91bcfc953484a181", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "3e67bd5e164be62771f28023494619d9cc685639059851ad0778a6b8028b5a86", - "start_line": 335, - "name": "clean", - "arity": 4 - }, - "digested_contents/3:230": { - "line": 230, - "guard": null, - "pattern": "file, latest, with_vsn?", - "kind": "defp", - "end_line": 241, - "ast_sha": "78d8ed2602de116168ade4017cd09fe48baeeabfa4be5599278dac8b78df4f4f", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "882be5181d527129923e3e8471f2178a53ad7e7d9cbf66825545ef0d8645927f", - "start_line": 230, - "name": "digested_contents", - "arity": 3 - }, - "remove_manifest/1:130": { - "line": 130, - "guard": null, - "pattern": "output_path", - "kind": "defp", - "end_line": 131, - "ast_sha": "9b0e99327022bc6bc5d3d6130db9c259cf3a67daeaaeecee08e19930ff2e0fdf", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "595ae3f0e242baf50e9085f78e9900c8a15034eb6c05bab8187374a41b3145bf", - "start_line": 130, - "name": "remove_manifest", - "arity": 1 - }, - "generate_digests/1:134": { - "line": 134, - "guard": null, - "pattern": "files", - "kind": "defp", - "end_line": 139, - "ast_sha": "d619f570606f46c41230888004c46a9841c49894ab341b637560c4427867dd33", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "57af9379235ef3b71f9b89a202437bdabb4fb8a452fc9e66f4c63e1a0244cbc6", - "start_line": 134, - "name": "generate_digests", - "arity": 1 - }, - "manifest_join/2:155": { - "line": 155, - "guard": null, - "pattern": "path, filename", - "kind": "defp", - "end_line": 155, - "ast_sha": "db85de8a3c10a413ce2950ea6bae6f30ab8c4885cc7c2dd0b470725b7d8a9a23", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "e9ae6ec8f1e51cd3f538f6e32ba2f21589d6468b37cc78deaea0106da33f4742", - "start_line": 155, - "name": "manifest_join", - "arity": 2 - }, - "filter_files/1:40": { - "line": 40, - "guard": null, - "pattern": "input_path", - "kind": "defp", - "end_line": 45, - "ast_sha": "468ac66da9d0ebea8a27d94b0e9e9916e92d85a966b2b411f2e63755eef54f97", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "2c380c648d3fe6e53c04c0847fcbc5f0c42b6dca2d3baaa3e087dabc1df2cd0b", - "start_line": 40, - "name": "filter_files", - "arity": 1 - }, - "fixup_sourcemaps/1:48": { - "line": 48, - "guard": "is_list(files)", - "pattern": "files", - "kind": "defp", - "end_line": 49, - "ast_sha": "8e2ab9e8a01416cab7920e04888f93dbb55548a374c9a35612eba5de2f44e927", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "0621c00a15718cc8bddf15c38b885b221e7e515142a3cd3a5356ebd56c7a454a", - "start_line": 48, - "name": "fixup_sourcemaps", - "arity": 1 - }, - "compile/3:20": { - "line": 20, - "guard": null, - "pattern": "input_path, output_path, with_vsn?", - "kind": "def", - "end_line": 34, - "ast_sha": "65f9e83690728cfd0d2bf84e9a8e08c977d0bfe3642ccb26a17c1b988d394d8c", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "7bc18e0675bf81ab4b7d1f17f5d4dcaa30bb7dbdd8f23613c384406fb205852c", - "start_line": 20, - "name": "compile", - "arity": 3 - }, - "write_manifest/3:115": { - "line": 115, - "guard": null, - "pattern": "latest, digests, output_path", - "kind": "defp", - "end_line": 127, - "ast_sha": "74f4e619a7344890da47f17e9dfcc4543e6851834d29a5cafa0d681299c363fb", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "4d0d9ee505495ae786cfb42c5d1542f4a6ecf2d3495fcfa85090282d89f8d737", - "start_line": 115, - "name": "write_manifest", - "arity": 3 - }, - "absolute_digested_url/3:317": { - "line": 317, - "guard": null, - "pattern": "url, digested_path, false", - "kind": "defp", - "end_line": 318, - "ast_sha": "1b99ee0fb078b936756c2ce3cd87220def54a5d585e83e630c430f315021661d", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "0d151b9abaff0c26e5f5cf7b638e05c8726ef6298861a5846702c7e127b369a5", - "start_line": 317, - "name": "absolute_digested_url", - "arity": 3 - }, - "maybe_fixup_sourcemap/2:52": { - "line": 52, - "guard": null, - "pattern": "sourcemap, files", - "kind": "defp", - "end_line": 56, - "ast_sha": "0a518bf03348d10b9a2e46af19609068c26465521cb8dda53c476af6900fc05a", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "238698ee9e5845a8f26e0fcebc34d8df62b6207aaa1ef78dce7982cc8f17ee30", - "start_line": 52, - "name": "maybe_fixup_sourcemap", - "arity": 2 - }, - "versions_to_clean/3:384": { - "line": 384, - "guard": null, - "pattern": "versions, max_age, keep", - "kind": "defp", - "end_line": 390, - "ast_sha": "c2b036ba94c21c67ebcda3358fa143ac81d507ae35b1510121866b719539de85", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "cfd61297bf61418d64124285c3b1951477de6e3b1377022b57479fc360a4d205", - "start_line": 384, - "name": "versions_to_clean", - "arity": 3 - }, - "fixup_sourcemap/2:60": { - "line": 60, - "guard": null, - "pattern": "%{} = sourcemap, files", - "kind": "defp", - "end_line": 68, - "ast_sha": "227cdf68a5c2948ede46aaaf80e884ee518d02a18a6b2e2fc56a3406fb639f04", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "881f54bdf33cd3efa0ff6c82ac047e9b904533d830957be8da21d81b90bc0e27", - "start_line": 60, - "name": "fixup_sourcemap", - "arity": 2 - }, - "compressed_extensions/0:165": { - "line": 165, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 167, - "ast_sha": "a56059485fea080ecb7a9c4f799d6734b3c9654c3a55e5878fdeb87856ce39b7", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "6fbeac4d1790d89df34976fb6d3e2837296a3f208093021dee993c75e98f6511", - "start_line": 165, - "name": "compressed_extensions", - "arity": 0 - }, - "generate_latest/1:72": { - "line": 72, - "guard": null, - "pattern": "files", - "kind": "defp", - "end_line": 77, - "ast_sha": "85b0ddd42c46c5e419677e98b9a5cf16c0250e670db0953bd5999bdb4dadc163", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "6deeb0070d4f52b0b0d0ce04403f22adf9161ce348d73593f876882a5a4609c1", - "start_line": 72, - "name": "generate_latest", - "arity": 1 - }, - "write_to_disk/2:191": { - "line": 191, - "guard": null, - "pattern": "file, output_path", - "kind": "defp", - "end_line": 227, - "ast_sha": "b6120221786f43d2fe5f094bb3e56c7106ddb2d74dfb80d5266b6b877a1a92af", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "563414a2b87388b5fb58d9b353b957b4e57f8e783c39cbdecd86862b8bddeaca", - "start_line": 191, - "name": "write_to_disk", - "arity": 2 - }, - "digest_stylesheet_asset_references/3:244": { - "line": 244, - "guard": null, - "pattern": "file, latest, with_vsn?", - "kind": "defp", - "end_line": 255, - "ast_sha": "73c9edb6399405dd7ea288fd7fbe7e9cf8bb432f0bd2c5d5a67fbf560bf8e8d3", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "b2afeb812b12e7aa19e34416e237bef7cc54711273630f8946c9c8004ef9254d", - "start_line": 244, - "name": "digest_stylesheet_asset_references", - "arity": 3 - }, - "load_compile_digests/1:82": { - "line": 82, - "guard": null, - "pattern": "output_path", - "kind": "defp", - "end_line": 84, - "ast_sha": "a50b8fb242e4e84e09d7b0d2431e690c1a5b5b7b76741d189b97353d81f211b2", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "a5cf96978375225cfdb3f23dcc27ac26cef594566f9313deaf6e7c8f9c6dea90", - "start_line": 82, - "name": "load_compile_digests", - "arity": 1 - }, - "remove_compressed_file/2:411": { - "line": 411, - "guard": null, - "pattern": "file, output_path", - "kind": "defp", - "end_line": 414, - "ast_sha": "d9fe05681ca2d55e5aa322b6489dd78710dc7e89dcd4ad6f0f0706bd0e50bd11", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "cb0b70354575fea5ed83e50533a4c1189316abdc54df8a6cad703eceaf478bbf", - "start_line": 411, - "name": "remove_compressed_file", - "arity": 2 - }, - "remove_files/2:397": { - "line": 397, - "guard": null, - "pattern": "files, output_path", - "kind": "defp", - "end_line": 403, - "ast_sha": "dc6c32543c6c6f584224fce7efd1e60add65ef5e2bdca9e0ecb135843f26b528", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "9f62f34a5d65aa89e9e53d2698b9c97e4e04f1d8db349acc875d06d2c40fc59d", - "start_line": 397, - "name": "remove_files", - "arity": 2 - }, - "compiled_file?/1:157": { - "line": 157, - "guard": null, - "pattern": "file_path", - "kind": "defp", - "end_line": 162, - "ast_sha": "c8e5f3158b7aa37a9e5dd1da5124616705e41b7639bdea46246bde3a17cd6d87", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "617bc995394019fc73350098af95cbf7edae5599db9bcfe04365c860c1d61662", - "start_line": 157, - "name": "compiled_file?", - "arity": 1 - }, - "manifest_join/2:154": { - "line": 154, - "guard": null, - "pattern": "\".\", filename", - "kind": "defp", - "end_line": 154, - "ast_sha": "cc4fa78313629727486fa0bbcfc9e96603bec93f7fd7686b2a96ffee6968b578", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "a7d9c40238b6e9e3a9eec9b3d12b5b3fd373fa85fce5f8cfa90aea9e8701f821", - "start_line": 154, - "name": "manifest_join", - "arity": 2 - }, - "migrate_manifest/2:101": { - "line": 101, - "guard": null, - "pattern": "_latest, _output_path", - "kind": "defp", - "end_line": 101, - "ast_sha": "2a8f200811f72b988ce9791c19b895cbfad87b6f2e24e4be3f903ab3d6920c87", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "7c9deeade4b650ac3b1fbb9bc46144744ba0e9e684107c670a2ea54b82a931b8", - "start_line": 101, - "name": "migrate_manifest", - "arity": 2 - }, - "migrate_manifest/2:100": { - "line": 100, - "guard": null, - "pattern": "%{\"version\" => 1} = manifest, _output_path", - "kind": "defp", - "end_line": 100, - "ast_sha": "32ff6897153814b2cff38928e2d56fcb01e7bee57df9c140ea4e90e533dcf1e2", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "86909da3bdd96fddddb8ee306b0877da5bd78b51493bae3ec6673480a36a172f", - "start_line": 100, - "name": "migrate_manifest", - "arity": 2 - }, - "save_manifest/4:103": { - "line": 103, - "guard": null, - "pattern": "files, latest, old_digests, output_path", - "kind": "defp", - "end_line": 110, - "ast_sha": "7bcff11f9064a33a2a00c4660606744f24e1c8f264dbc4a69e23c74757182914", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "0bdbcd1359346fa15b948398392ca43a1822f2e6cb58d578db31f5a5485987c7", - "start_line": 103, - "name": "save_manifest", - "arity": 4 - }, - "map_file/2:170": { - "line": 170, - "guard": null, - "pattern": "file_path, input_path", - "kind": "defp", - "end_line": 187, - "ast_sha": "9dd1f4caa5b74c514990da7192656f06634425f560d70f5ea7acb793b9aa5b0e", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "83c1d4e36266335392383739d68342cdb79773fe2f833c3bcf860abe53201839", - "start_line": 170, - "name": "map_file", - "arity": 2 - }, - "relative_digested_path/2:305": { - "line": 305, - "guard": null, - "pattern": "digested_path, true", - "kind": "defp", - "end_line": 306, - "ast_sha": "29360e0cefcb2509a7c702cf9ce181798a80656299c427034837a951e0977cd4", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "18036ac211b5f35cbbf3ae545a911c589955617a135b96c58126f19fd10baafa", - "start_line": 305, - "name": "relative_digested_path", - "arity": 2 - }, - "group_by_logical_path/1:393": { - "line": 393, - "guard": null, - "pattern": "digests", - "kind": "defp", - "end_line": 394, - "ast_sha": "3cbe12b05b2d08b83a25a06e8c2af5cc84a6e08e9f7d020d9e7ac7bc8ab3d448", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "96a7e55813c81deba04ea98c0ca9ad55597e3170aa4e08cf5f24d0a1cf908941", - "start_line": 393, - "name": "group_by_logical_path", - "arity": 1 - }, - "clean_all/1:356": { - "line": 356, - "guard": null, - "pattern": "path", - "kind": "def", - "end_line": 369, - "ast_sha": "30c0e8596ab80a05614c794a291bbd68ac568bfdcce71b0096d68cad6fd86812", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "5a90006c7e9518fd1940ecf76f0dd674c021ad44a171a5b966a0fc7254c4a4c6", - "start_line": 356, - "name": "clean_all", - "arity": 1 - }, - "digest_javascript_asset_references/2:260": { - "line": 260, - "guard": null, - "pattern": "file, latest", - "kind": "defp", - "end_line": 264, - "ast_sha": "0d84c23a0698263417ab993e043a6cd9cee30f70c9f5a2c646c5bff439d9056d", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "1bc20eeb2d61dadf87493cb8b9cde1ec306b7912c41d181a2d9b76b3fd79b3b0", - "start_line": 260, - "name": "digest_javascript_asset_references", - "arity": 2 - }, - "absolute_digested_url/3:314": { - "line": 314, - "guard": null, - "pattern": "url, digested_path, true", - "kind": "defp", - "end_line": 315, - "ast_sha": "66c5451191be2dfc983ab59ce1466bcf38a4f44a53555ae51b8651491911ac0b", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "6721aacf2e562502fe34128a764081009a8f55e0adab97b8af56eab85b5adf87", - "start_line": 314, - "name": "absolute_digested_url", - "arity": 3 - }, - "digested_url/4:276": { - "line": 276, - "guard": null, - "pattern": "<<\"/\"::binary, relative_path::binary>>, _file, latest, with_vsn?", - "kind": "defp", - "end_line": 279, - "ast_sha": "3ffd10dd93e6311867c1003be7182c496c43464561b7f1266ad362a3ff930f8b", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "2e9ec4dc93ab176b30bd0a7d2b1b1798531c71781b4f239bb8138a332b9c2b0c", - "start_line": 276, - "name": "digested_url", - "arity": 4 - }, - "digested_url/4:283": { - "line": 283, - "guard": null, - "pattern": "url, file, latest, with_vsn?", - "kind": "defp", - "end_line": 301, - "ast_sha": "1587fc38f72dfd2df7cedb3984472641cde4d82a36152a3537aa1b47dee43748", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "44eb71259e6f4b4db46c50b88412ebb52267acfeeb1fda5377b5c40981168db1", - "start_line": 283, - "name": "digested_url", - "arity": 4 - }, - "absolute_digested_url/2:320": { - "line": 320, - "guard": null, - "pattern": "url, digested_path", - "kind": "defp", - "end_line": 321, - "ast_sha": "9670b24f5c758d3ec7d2a63661c1e778e61851d4c25840aa463a1889daad2ee8", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "7458554c1211b7ffd401c1ad8b10b2cb5decf16193e159e8fcd4a340cd404943", - "start_line": 320, - "name": "absolute_digested_url", - "arity": 2 - }, - "build_digest/1:144": { - "line": 144, - "guard": null, - "pattern": "file", - "kind": "defp", - "end_line": 150, - "ast_sha": "3b8c20bf0f892c1a1c11797cc659497669e5ea53ccd2ef7ff39feda12c0e3ae1", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "f45bcad07d553d703f031e2d17400d87343774e0b75dbccc34b482b0ef792ea3", - "start_line": 144, - "name": "build_digest", - "arity": 1 - }, - "digest_javascript_map_asset_references/2:268": { - "line": 268, - "guard": null, - "pattern": "file, latest", - "kind": "defp", - "end_line": 272, - "ast_sha": "5a2e09e1757568f50ab7823d9ccc89dfc7e8431b9e39635990e9fcb2269e4303", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "cacb165492550850ea4d3a419af947e5bf8557cc97929fdce992fe44905b7056", - "start_line": 268, - "name": "digest_javascript_map_asset_references", - "arity": 2 - }, - "relative_digested_path/2:308": { - "line": 308, - "guard": null, - "pattern": "digested_path, false", - "kind": "defp", - "end_line": 309, - "ast_sha": "cac99228af0c6c470d5511abc7742587ca67f3ef0f332a60ed286ef80b99e828", - "source_file": "lib/phoenix/digester.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/digester.ex", - "source_sha": "57d0c325f49f5cb51c92a9ec081fd441d4ec524023d33020ae4aca956ee24ba5", - "start_line": 308, - "name": "relative_digested_path", - "arity": 2 - } - }, - "Phoenix.CodeReloader.MixListener": { - "handle_call/3:34": { - "line": 34, - "guard": null, - "pattern": "{:purge, apps}, _from, state", - "kind": "def", - "end_line": 39, - "ast_sha": "172f90fc043460af7436c18b18ce5445ebad09940d3cc6dd1ae71f0069c65b54", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "92dd50d63e8fcbc18322349bdc22afdfd8a475f8da48d0e7fcd4d76b0e3c601c", - "start_line": 34, - "name": "handle_call", - "arity": 3 - }, - "handle_info/2:43": { - "line": 43, - "guard": null, - "pattern": "{:modules_compiled, info}, state", - "kind": "def", - "end_line": 58, - "ast_sha": "c49639fb8b72e7c70528a0cbd1b36744f23f728b8478a4fc2a32a4eb410d4cdb", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "75a6844569f7acc1771172a6ac29a21b17967aa350e370f6e02bdb2f07ca092f", - "start_line": 43, - "name": "handle_info", - "arity": 2 - }, - "handle_info/2:62": { - "line": 62, - "guard": null, - "pattern": "_message, state", - "kind": "def", - "end_line": 63, - "ast_sha": "728932b338eac35c119f0753a66c52537e899c474f33f4919118f8555a9a0a5c", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "c81cec00239d40f9ff67646993cd33a2d4d16dd15476c3fde91fd0afdf7dd7fb", - "start_line": 62, - "name": "handle_info", - "arity": 2 - }, - "init/1:29": { - "line": 29, - "guard": null, - "pattern": "{}", - "kind": "def", - "end_line": 30, - "ast_sha": "657f1484cead00c517722612510816f027304ce03b152b10609ac53350df4c33", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "251a745a3093235b9c1affb8f9a4c0ece8393460283a33b1d4788ebd1bef12b5", - "start_line": 29, - "name": "init", - "arity": 1 - }, - "purge/1:24": { - "line": 24, - "guard": null, - "pattern": "apps", - "kind": "def", - "end_line": 25, - "ast_sha": "8bb81b165868cb611a40506fe388550f6def00a90af49e09d7bf1389f23ef716", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "4c5f7fb829c7b6b65c03dc88ddf55bb1e7d455e42613f76d1337629c9d1e78d8", - "start_line": 24, - "name": "purge", - "arity": 1 - }, - "purge_modules/1:66": { - "line": 66, - "guard": null, - "pattern": "modules", - "kind": "defp", - "end_line": 69, - "ast_sha": "c862cf5ce9d24668d3417a43f413947856878af32e45ab19f62fb04b4bb7fb7d", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "598bd6106b26b6f38e22f835dbd7435e661a0a75e23bf2c7416356a32fc0473b", - "start_line": 66, - "name": "purge_modules", - "arity": 1 - }, - "start_link/1:9": { - "line": 9, - "guard": null, - "pattern": "_opts", - "kind": "def", - "end_line": 10, - "ast_sha": "2e2edfc408d9fa467a6ba05c26264019277120c7d72a528678be9b560661aa1e", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "1abcdfcee769ad69b614e50b5e01da003d46d085ca47734f9c42a136a651302c", - "start_line": 9, - "name": "start_link", - "arity": 1 - }, - "started?/0:14": { - "line": 14, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 15, - "ast_sha": "31f5f95e58dbb61a90025ce5597810d1e7ba7e6f959641ce38d713c962ba3cc8", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "807d9c73b91b44b540e154c5a557c108b8b1bf96207b308fa534d77a491936e6", - "start_line": 14, - "name": "started?", - "arity": 0 - }, - "terminate/2:4": { - "line": 4, - "guard": null, - "pattern": "_reason, _state", - "kind": "def", - "end_line": 4, - "ast_sha": "2d755a9ef78c6133526a504530cd209ae244ac931951ac891fbba9b596d281c7", - "source_file": "lib/phoenix/code_reloader/mix_listener.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/code_reloader/mix_listener.ex", - "source_sha": "715fd392f3fa992b0158acc1916fe5eb6f622df851765d3059093d71ccd59590", - "start_line": 4, - "name": "terminate", - "arity": 2 - } - }, - "Phoenix.VerifiedRoutes": { - "build_conn_forward_path/3:1050": { - "line": 1050, - "guard": null, - "pattern": "%Plug.Conn{} = conn, router, path", - "kind": "defp", - "end_line": 1056, - "ast_sha": "58beb26e867ce72f09c9bfff6cd87f9fd2b1108d6ede73104c3c5a47aecbccda", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "01319430eb83566502e075dfd54453728abc5d20f45a5afd30dc3b85c967d203", - "start_line": 1050, - "name": "build_conn_forward_path", - "arity": 3 - }, - "url/2:539": { - "line": 539, - "guard": null, - "pattern": "conn_or_socket_or_endpoint_or_uri, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", - "kind": "defmacro", - "end_line": 547, - "ast_sha": "682dc7d3b86f658eed2b68c4a980fb1ca6fa7d73803c4e6845fcddbe66ebacf3", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "a2d8587472f584b2b61f2b684ff66913ac0087bacf8be239151556963033940e", - "start_line": 539, - "name": "url", - "arity": 2 - }, - "attr!/2:1021": { - "line": 1021, - "guard": null, - "pattern": "env, :endpoint", - "kind": "defp", - "end_line": 1023, - "ast_sha": "035d8f4e6ee641fe748ca5d8a45b5256bb00461c61daee677ae68af5be0c61f2", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "f0d8200f476e7f8638dac8afc56f099afe2fa3c3ef19fa0ac6cd038d834fca87", - "start_line": 1021, - "name": "attr!", - "arity": 2 - }, - "static_path/2:678": { - "line": 678, - "guard": null, - "pattern": "%Plug.Conn{private: private}, path", - "kind": "def", - "end_line": 681, - "ast_sha": "1db4f06c26c3f4e59a20371461023e9c96a07ef5e427b18934fcaa9150ef578b", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "742190ca97804bef54f14efaa2f475c6070749ff95e51778aae930fa157cb1d9", - "start_line": 678, - "name": "static_path", - "arity": 2 - }, - "verify_segment/3:807": { - "line": 807, - "guard": null, - "pattern": "[_ | _], route, _acc", - "kind": "defp", - "end_line": 809, - "ast_sha": "0ceb4d4d42e8d32454980208c6647d73d24473d28e7d537e0b42702a24eb3e54", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "c58cf7344af8b110bf22711a9f9704121b5de9374919d5e7ff6e27cb9afb0a0d", - "start_line": 807, - "name": "verify_segment", - "arity": 3 - }, - "build_own_forward_path/3:1040": { - "line": 1040, - "guard": null, - "pattern": "conn, router, path", - "kind": "defp", - "end_line": 1045, - "ast_sha": "a3db78d332b93307ab35c0694b3e1a30d6bc8c850f2b03a0440133fb9b9f3708", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "265159a0f4396856028592e669be42a9ea17c4e6fd50cd1b3dd8190b9a738708", - "start_line": 1040, - "name": "build_own_forward_path", - "arity": 3 - }, - "verify_segment/3:768": { - "line": 768, - "guard": null, - "pattern": "[<<\"/\"::binary, _::binary>> = segment | rest], route, acc", - "kind": "defp", - "end_line": 775, - "ast_sha": "5c22453031e75ac7394cbf882d39efb0e47a6b2b2f84d04110aa3154058078e4", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "4dcf049ad408ad9488cb18b064935431aa070334073cda5e6349de37160a6263", - "start_line": 768, - "name": "verify_segment", - "arity": 3 - }, - "path/3:445": { - "line": 445, - "guard": null, - "pattern": "_endpoint, _router, other", - "kind": "defmacro", - "end_line": 445, - "ast_sha": "3f417d2776987fc7e69b505b425bbe132dd3293f82a0de75feb1b0b245d8a556", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "74124352a4be6c4d67e8c6669ec318beb472a8d82786528093ec828d2c763d18", - "start_line": 445, - "name": "path", - "arity": 3 - }, - "static_path?/2:1036": { - "line": 1036, - "guard": null, - "pattern": "path, statics", - "kind": "defp", - "end_line": 1037, - "ast_sha": "51693a41f2e5e98d3c34965aa173d3d1c1d20892dc99a4b603a52d249475d470", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "a3f1e5da5b3bbe06c674a7a1a27b0a4aa5afa79c464f5d8e117486b38fad3d4c", - "start_line": 1036, - "name": "static_path?", - "arity": 2 - }, - "append_params/2:738": { - "line": 738, - "guard": "is_map(params) or is_list(params)", - "pattern": "path, params", - "kind": "defp", - "end_line": 739, - "ast_sha": "ad3924cb8f0e04b7a9ba59b8fcc6221c7825c7f269f8406265b0c01aac10cf02", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "e041040ededbe072e8f50f4e4b5e4c540f382fcccadd4ce1edaf19078a221cf7", - "start_line": 738, - "name": "append_params", - "arity": 2 - }, - "verify_segment/2:758": { - "line": 758, - "guard": null, - "pattern": "[<<\"/\"::binary, _::binary>> | _] = segments, route", - "kind": "defp", - "end_line": 758, - "ast_sha": "d1f90e46d434f14ca57d80947db48bce2e14ac859a33f8d7acc9cd3024f9d9fc", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "22565f0d61ee2024015b3a5f9e9f5383bb23b68eb8377ef6b4d34c743d1e1bdd", - "start_line": 758, - "name": "verify_segment", - "arity": 2 - }, - "unverified_path/4:718": { - "line": 718, - "guard": null, - "pattern": "%URI{} = uri, _router, path, params", - "kind": "def", - "end_line": 719, - "ast_sha": "48bfcf002e72af26682001672f7f4d8c378f605aed740c39219a4d749d266a8f", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "748f926ed0ddfb80d878f6ab28ccf2ad17f3f0fe5cb9526e036e04c4b4fcd920", - "start_line": 718, - "name": "unverified_path", - "arity": 4 - }, - "guarded_unverified_url/3:626": { - "line": 626, - "guard": null, - "pattern": "%Plug.Conn{private: private}, path, params", - "kind": "defp", - "end_line": 629, - "ast_sha": "1b272cf989fe807c59df8c4f86b3061b59526dc68844e2564a2f674459414982", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "78260e3684bc0e29c50e9bf2524b651afe29dee7e7493111998618761be088a9", - "start_line": 626, - "name": "guarded_unverified_url", - "arity": 3 - }, - "expand_alias/2:334": { - "line": 334, - "guard": null, - "pattern": "{:__aliases__, _, _} = alias, env", - "kind": "defp", - "end_line": 335, - "ast_sha": "0adc16b3c706fea8474fd983fb8b9289b8c286ca0f8d13e92c0865cae086158e", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "02dafd1ea2b8b593ef7a47900ce17bf6437216b66645af2703a43fedc98355e9", - "start_line": 334, - "name": "expand_alias", - "arity": 2 - }, - "static_path/2:685": { - "line": 685, - "guard": null, - "pattern": "%URI{} = uri, path", - "kind": "def", - "end_line": 686, - "ast_sha": "7f40926ac8737d60bb4332f3869e4243a39399b1bfdcd79ac4e0c51dbfebee0d", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "caed655409329909626f7ee2ca3bff1a0285224f29864d4f7253d7a4f13721a4", - "start_line": 685, - "name": "static_path", - "arity": 2 - }, - "unverified_url/3:621": { - "line": 621, - "guard": "(is_map(params) or is_list(params)) and is_binary(path)", - "pattern": "conn_or_socket_or_endpoint_or_uri, path, params", - "kind": "def", - "end_line": 623, - "ast_sha": "e93a23e0d0b1151cbeaa7f59a97ab83a07f93177cff0767f92b2fa39c57ef5ca", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "9d001c26ae0732de00f6302880d6cbbcfea01d359d10babf74dd57bc93400af7", - "start_line": 621, - "name": "unverified_url", - "arity": 3 - }, - "guarded_unverified_url/3:637": { - "line": 637, - "guard": null, - "pattern": "%URI{} = uri, path, params", - "kind": "defp", - "end_line": 638, - "ast_sha": "c5c09cfcdf686c0926a69533e9c646f7cf07320644ea577964561874f389c846", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "93acbf727dd1f85d1deeefc5a343e1b629ff1c41caaaa67fb95e47f574edbeac", - "start_line": 637, - "name": "guarded_unverified_url", - "arity": 3 - }, - "url/3:569": { - "line": 569, - "guard": null, - "pattern": "_conn_or_socket_or_endpoint_or_uri, _router, other", - "kind": "defmacro", - "end_line": 569, - "ast_sha": "df6a4d9e6fb9dd48a0f551660216131d425952bf140be917bf0e504e6493d0b4", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "0d553c055f384ecfd849b39ce55975a1e0704be49daf15fa355ad43d323ebfce", - "start_line": 569, - "name": "url", - "arity": 3 - }, - "raise_invalid_route/1:406": { - "line": 406, - "guard": null, - "pattern": "ast", - "kind": "defp", - "end_line": 408, - "ast_sha": "3dc513d21b59bdad6f181d3f50a1fe1acce6c5d0d36704d8a3140f148ca16eb7", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "54af1addda61a2ed37a905b3387812d3811fea58e00832377cbe60adcff6a533", - "start_line": 406, - "name": "raise_invalid_route", - "arity": 1 - }, - "to_param/1:910": { - "line": 910, - "guard": null, - "pattern": "false", - "kind": "defp", - "end_line": 910, - "ast_sha": "cf485e3b01a68a4ae51a615164368a5e004a8ec3c4a8e5bbf57d23b03e221b79", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "1ec4fd8b598c35aa8e676242afd165dfc96f0ff2a49db6531d24c4c55fce334b", - "start_line": 910, - "name": "to_param", - "arity": 1 - }, - "verify_segment/3:785": { - "line": 785, - "guard": null, - "pattern": "[<<\"?\"::binary, static_query_segment::binary>> | rest], route, acc", - "kind": "defp", - "end_line": 786, - "ast_sha": "32eaa57c62b493336f59f3b7972e2b1fcf39a4ee8f60de800a9e469316214088", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "9cd31a18f41f1d58d65cebff842a0f2d946d1a0064c4d3d787b46bcd5c177150", - "start_line": 785, - "name": "verify_segment", - "arity": 3 - }, - "expand_alias/2:337": { - "line": 337, - "guard": null, - "pattern": "other, _env", - "kind": "defp", - "end_line": 337, - "ast_sha": "5c1eb33d03a28c7c203db769680afd2f87bb2aec41bf23a862d63b9cc6b88bb9", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b64d75b4d6433137fe401881882cacc900ed44f9358ac7a1d7fe346e1aa14e9c", - "start_line": 337, - "name": "expand_alias", - "arity": 2 - }, - "unverified_path/4:722": { - "line": 722, - "guard": null, - "pattern": "%_{endpoint: endpoint}, router, path, params", - "kind": "def", - "end_line": 723, - "ast_sha": "b30b1e78381a08a04575a5e99dcdda18023b24df34c1fdd0512b7ddb975ef6a1", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "9112240a69bc48e9cda491b3632fb232bfed65a02bab914f42a731a8151a621d", - "start_line": 722, - "name": "unverified_path", - "arity": 4 - }, - "raise_invalid_query/1:855": { - "line": 855, - "guard": null, - "pattern": "route", - "kind": "defp", - "end_line": 857, - "ast_sha": "ade55884af8ce1760491baa96974fed1168d05ac3dca5f13ea4ec34dc066b46e", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "e10913c3ccf3ee9badf159a83bf7dd2da6de2ade6d2ba79a672a6e01f1856f21", - "start_line": 855, - "name": "raise_invalid_query", - "arity": 1 - }, - "to_param/1:911": { - "line": 911, - "guard": null, - "pattern": "true", - "kind": "defp", - "end_line": 911, - "ast_sha": "e2450a89e6beec2574eb810707567161b09818a7ce3959ade84532d45bbf1501", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "f2e33fb29f90fdb52938d36e082374038c022d31f6604e5e016d2eb4db605936", - "start_line": 911, - "name": "to_param", - "arity": 1 - }, - "__struct__/0:219": { - "line": 219, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 219, - "ast_sha": "263881a97b11577d1b9ea2e0e4bce4f4f0319124db2b0b5d1780ab3f53674b95", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "6b0f19d7ab0dcc97db52ddf76d95137aab2a963a6fa18de787d94f2d28c6ff11", - "start_line": 219, - "name": "__struct__", - "arity": 0 - }, - "to_param/1:912": { - "line": 912, - "guard": null, - "pattern": "data", - "kind": "defp", - "end_line": 912, - "ast_sha": "2188c730bed14579bddf3a4b30bafc421f1b4231c8d7925a3f7b29e7b45f24df", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "f01cd0e9679f9801f15648655ced43ea67cafb7e7f4427127c3c39de76482218", - "start_line": 912, - "name": "to_param", - "arity": 1 - }, - "split_test_path/1:326": { - "line": 326, - "guard": null, - "pattern": "test_path", - "kind": "defp", - "end_line": 331, - "ast_sha": "78cf67d0e790c023d51005b84ff3b306804fa6429d07f68028c13e7735671b25", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "50f0c9e400824d7b573d7687bce35f47a6b056e2e081f2ec696701a924b865b7", - "start_line": 326, - "name": "split_test_path", - "arity": 1 - }, - "append_params/2:736": { - "line": 736, - "guard": "params == %{} or params == []", - "pattern": "path, params", - "kind": "defp", - "end_line": 736, - "ast_sha": "68c29823ef0e7eeb26dbc4ea643e9e1badbb2f50787c803de00ac13e96b15aa0", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "98e19612fefb6f627d58700069d7f5c455b9907fee1e4ff26a29efd11cb87984", - "start_line": 736, - "name": "append_params", - "arity": 2 - }, - "unverified_path/3:708": { - "line": 708, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 708, - "ast_sha": "712cac5b68f49b31a1b5bb0871832d3d760a39167adb009da35dacf02d6472cf", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "ef0848fd17762d4b3da907ff456d28daf7ffbba40f23059b30b94032bb4f8c30", - "start_line": 708, - "name": "unverified_path", - "arity": 3 - }, - "static_integrity/2:882": { - "line": 882, - "guard": null, - "pattern": "%_{endpoint: endpoint}, path", - "kind": "def", - "end_line": 883, - "ast_sha": "342ef67e9088d11ce910bc999eeef83b014c34ad445ae77b4c7e8ac2e704fa28", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "568203a323304ae4c516731437822b35e830fe470c7b1cf26ee92c935c27dd2a", - "start_line": 882, - "name": "static_integrity", - "arity": 2 - }, - "__encode_query__/1:891": { - "line": 891, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 891, - "ast_sha": "da492e005acdddfd4d2d03ff54fa29263da147b69f325b040dcb7ed7e4ebd11d", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "fcfdb988948a62fedfbd3b0386c75556069b7a0f35c83d0811aee00f3a9bc8da", - "start_line": 891, - "name": "__encode_query__", - "arity": 1 - }, - "maybe_sort_query/2:905": { - "line": 905, - "guard": null, - "pattern": "query, true", - "kind": "defp", - "end_line": 906, - "ast_sha": "4ce4e8df43b0bd3b262acabbe53a157c6b0566f68ae216215f1dc4a77f1c02e9", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "9ce2611bd19e853d89247f3790e45130d1889c2d5efdcd45dd03ab5e0ea2213f", - "start_line": 905, - "name": "maybe_sort_query", - "arity": 2 - }, - "__encode_query__/2:893": { - "line": 893, - "guard": "is_list(dict) or\n (is_map(dict) and\n not (is_map(dict) and is_map_key(:__struct__, dict) and is_atom(map_get(:__struct__, dict))))", - "pattern": "dict, sort?", - "kind": "def", - "end_line": 897, - "ast_sha": "79d135599d6e235a0b417bbbbd423e62bc4114de1269cd78de1f256d992b0742", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b61eb40dc569c77344ab0cbb2d01d2d87eaacdca5c6d1a5eeb2f324860e17854", - "start_line": 893, - "name": "__encode_query__", - "arity": 2 - }, - "static_path/2:689": { - "line": 689, - "guard": null, - "pattern": "%_{endpoint: endpoint}, path", - "kind": "def", - "end_line": 690, - "ast_sha": "f41bbba47ba162c9a3e4b4e819534d8db2975aba2101af444e2fb2b7732433a1", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "15c21fd3f9e91b26df0221bc8c910feaacf1e4e8045fef76d7caedfc06b4b0ac", - "start_line": 689, - "name": "static_path", - "arity": 2 - }, - "__using__/2:246": { - "line": 246, - "guard": null, - "pattern": "mod, opts", - "kind": "def", - "end_line": 270, - "ast_sha": "0b402e615c188842756a71b68bde80619ab38d80cf04c46dff2ed8146ee4323f", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "cfe1bc7fd5cb52c52b18f74f79d9cba61e259f0c6eea98a199affe1ff9bf7067", - "start_line": 246, - "name": "__using__", - "arity": 2 - }, - "verify_query/3:838": { - "line": 838, - "guard": null, - "pattern": "[\"=\" | rest], route, acc", - "kind": "defp", - "end_line": 839, - "ast_sha": "92498feb7834d40d0ceab794ebc385dc3076164e8b677bbbc75f349ebb4a8584", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "909705504460a3b23cdb95051c5769840f36f61e08aee5b851a2e50a93293008", - "start_line": 838, - "name": "verify_query", - "arity": 3 - }, - "__encode_query__/2:901": { - "line": 901, - "guard": null, - "pattern": "val, _sort?", - "kind": "def", - "end_line": 901, - "ast_sha": "31c8ebe0ef090a9b24ce095c5f184ec79b986fcabced5fc7b1aa8bd0b7e18fbf", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "c4a1ded39450d5724d98ff157422e8c7215881492530cc5a19acd948218b44dc", - "start_line": 901, - "name": "__encode_query__", - "arity": 2 - }, - "__verify__/1:313": { - "line": 313, - "guard": "is_list(routes)", - "pattern": "routes", - "kind": "def", - "end_line": 320, - "ast_sha": "26ba035746aee2c1d150bc150c3e8b266d1e78aaaed9c1f62185e7f0cf7f58be", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "6015421613c6ae00ee75da5eaa73916aabb9e6ba31399d2131f4cd1ed5e54025", - "start_line": 313, - "name": "__verify__", - "arity": 1 - }, - "encode_segment/1:751": { - "line": 751, - "guard": null, - "pattern": "data", - "kind": "defp", - "end_line": 754, - "ast_sha": "40330b5cadad8aaeb5f14cb7da8298845aa0aa5f167a45c5129deff61d51e085", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "6b9a3f1b4c453010e2886278248b6432b5160f0403eeae961c7d84d83d9b74d3", - "start_line": 751, - "name": "encode_segment", - "arity": 1 - }, - "verify_query/3:836": { - "line": 836, - "guard": null, - "pattern": "[], _route, acc", - "kind": "defp", - "end_line": 836, - "ast_sha": "7f8c0ed28af8fef1541b7861a0e2e369955f46b26ef01efe354e7965fcb81083", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "ecafca31ca5f9c0d99ed258c5a85c3e0873f93666f2e37508405210dd085c705", - "start_line": 836, - "name": "verify_query", - "arity": 3 - }, - "__using__/1:225": { - "line": 225, - "guard": null, - "pattern": "opts", - "kind": "defmacro", - "end_line": 241, - "ast_sha": "5815d3b815808c22db1824310487f21c7661a2ceb70676e9e8e60dbfee28e646", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "c67d1ba990d01bbc587755da98fa80d26c12780abbb8ce13ecc8ba17d3a1a6d7", - "start_line": 225, - "name": "__using__", - "arity": 1 - }, - "path/2:480": { - "line": 480, - "guard": null, - "pattern": "_conn_or_socket_or_endpoint_or_uri, other", - "kind": "defmacro", - "end_line": 480, - "ast_sha": "2787a5f5b23602cc50be7dd6eb718a21b5f44b7dfe7a5057d5eeb13930f5fdfd", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b470291bbcf412e4404b60cf3068581f152814e8e3508c32aec448afbf77ce6f", - "start_line": 480, - "name": "path", - "arity": 2 - }, - "unverified_path/4:710": { - "line": 710, - "guard": null, - "pattern": "%Plug.Conn{} = conn, router, path, params", - "kind": "def", - "end_line": 715, - "ast_sha": "7c0d10153dea2b6ef04181eb225821398f6c732fb8280707e354fdbaf60eb43f", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "337fa9d163f808fadbc58f61e3a3dec17b0d1bad3f496a083b84a90aab84d6eb", - "start_line": 710, - "name": "unverified_path", - "arity": 4 - }, - "verify_query/3:851": { - "line": 851, - "guard": null, - "pattern": "_other, route, _acc", - "kind": "defp", - "end_line": 852, - "ast_sha": "ff7fba30e0ca646179d20023acdc9ed59f7e656fa766fa0a0866a2a6cd6927f7", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "257e48e9edce2bc85730718392f4070f1a607644b4496a07315da3fd7d2d0a0e", - "start_line": 851, - "name": "verify_query", - "arity": 3 - }, - "url/2:550": { - "line": 550, - "guard": null, - "pattern": "_conn_or_socket_or_endpoint_or_uri, other", - "kind": "defmacro", - "end_line": 550, - "ast_sha": "2787a5f5b23602cc50be7dd6eb718a21b5f44b7dfe7a5057d5eeb13930f5fdfd", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "a7f5a1dbd4260f8a476a8f30bc483682a19b368177a74f8baecfc293012c7ca0", - "start_line": 550, - "name": "url", - "arity": 2 - }, - "warn_location/2:944": { - "line": 944, - "guard": null, - "pattern": "meta, %{line: line, file: file, function: function, module: module}", - "kind": "defp", - "end_line": 946, - "ast_sha": "8de72d9738543a9f1cfd97ba90490eea8b3dbb55887cdc2113b38be057a358f9", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "14b82d1cd0aa82aedf0e05f68e94420b032401a4a4446116ee73a2fef915e7b9", - "start_line": 944, - "name": "warn_location", - "arity": 2 - }, - "verify_segment/3:813": { - "line": 813, - "guard": null, - "pattern": "[], _route, acc", - "kind": "defp", - "end_line": 813, - "ast_sha": "699bcbccab5d404858deba881ac9d76ff04bd4dc208dec6ca22aacac392a7e20", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "05981265f54bebebf0030f1519c48a3dd8b316e5f223d83ee855f9019998b2dd", - "start_line": 813, - "name": "verify_segment", - "arity": 3 - }, - "to_param/1:908": { - "line": 908, - "guard": "is_integer(int)", - "pattern": "int", - "kind": "defp", - "end_line": 908, - "ast_sha": "fc0a53d67074be1b3315b576026e16d19187f2a672d53756e7f0754bcd8d184a", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b176908d74f08eed0e4d5c951396e376af92fe6cb74bfdca191f425d041bcb7b", - "start_line": 908, - "name": "to_param", - "arity": 1 - }, - "build_route/5:914": { - "line": 914, - "guard": null, - "pattern": "route_ast, sigil_p, env, endpoint_ctx, router", - "kind": "defp", - "end_line": 940, - "ast_sha": "620ac3e06c453ef36b9107eb1f1f7968a79d9539bbbfa6acf4882f4471585407", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b0e26a087808fac4814bfa4de29cbea17b8b6ca95f16ad1b2f03efe2f7513baf", - "start_line": 914, - "name": "build_route", - "arity": 5 - }, - "url/3:557": { - "line": 557, - "guard": null, - "pattern": "conn_or_socket_or_endpoint_or_uri, router, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", - "kind": "defmacro", - "end_line": 566, - "ast_sha": "37b5bf0561732cbc5ba34ea9b56590d79e9a26c5728935d66d044d27fcfdb989", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "8aad4351397db351962fc56dd9538294cbf13bf10779b48a3cd547638a077c3c", - "start_line": 557, - "name": "url", - "arity": 3 - }, - "guarded_unverified_url/3:633": { - "line": 633, - "guard": null, - "pattern": "%_{endpoint: endpoint}, path, params", - "kind": "defp", - "end_line": 634, - "ast_sha": "9f2cde53921934913e384e759aad102ca6f1de9bf1a8b83cd1542434d204c1d1", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "5ef91c60b7c483a9fbbbee05a92f80f90821bc39d08ea22364385deb424977eb", - "start_line": 633, - "name": "guarded_unverified_url", - "arity": 3 - }, - "path_with_script/2:1060": { - "line": 1060, - "guard": null, - "pattern": "path, []", - "kind": "defp", - "end_line": 1060, - "ast_sha": "c2dec8193e4fbe1790877b6f68eda4a42f219538978a80a77fc85da4bfd38940", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "fdb5fc337dae0751b2159bfc44fe8c4298db473a4e4e297a4993fd92e7f9e29e", - "start_line": 1060, - "name": "path_with_script", - "arity": 2 - }, - "concat_url/3:653": { - "line": 653, - "guard": "is_binary(path)", - "pattern": "url, path, params", - "kind": "defp", - "end_line": 654, - "ast_sha": "0f89dfb154974925dce78b46ce21e27d5df4b242c8f8478c6fb9620f3b72509b", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "2b0362934fb74043fcfbb4352f562ebdbab4924866559568d4cc33e442865833", - "start_line": 653, - "name": "concat_url", - "arity": 3 - }, - "guarded_unverified_url/3:645": { - "line": 645, - "guard": null, - "pattern": "other, path, _params", - "kind": "defp", - "end_line": 648, - "ast_sha": "8c21c464b01ca9915352473db9ad573fd2c7fcadf09fd679c261c4b379501dff", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "f55c67c4534be03d459c9e71be60a1f29a19d61b468aca42c17e80bdb0a61592", - "start_line": 645, - "name": "guarded_unverified_url", - "arity": 3 - }, - "static_path/2:693": { - "line": 693, - "guard": "is_atom(endpoint)", - "pattern": "endpoint, path", - "kind": "def", - "end_line": 694, - "ast_sha": "6755c53859bb0b7e85a5a3068213de93b94543ab79300a0899777fd47c4e87d2", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "eb5873caabf800000baaf1684b530c980d342a740ec661ebc5ddc6d79b3581db", - "start_line": 693, - "name": "static_path", - "arity": 2 - }, - "static_url/2:604": { - "line": 604, - "guard": null, - "pattern": "other, path", - "kind": "def", - "end_line": 607, - "ast_sha": "2e82ddfa49392608c1ceeecde04b414c4305f0b2dfffaf45c89aaa85ea5dde6f", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "43db59e9f158bc7f1899dffc706d9f8dd9ca0f0cb04ef72ddd8d9489a4ec7485", - "start_line": 604, - "name": "static_url", - "arity": 2 - }, - "sigil_p/2:361": { - "line": 361, - "guard": null, - "pattern": "{:<<>>, _meta, _segments} = route, extra", - "kind": "defmacro", - "end_line": 368, - "ast_sha": "54821b040a1f4976ec40b2757c0f88d07e76bafd447bbd2a178b061e0c58e9b5", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "3be08178e952876e8aec4a988ffc4d6d063750c197aa04fc245e518a453302e8", - "start_line": 361, - "name": "sigil_p", - "arity": 2 - }, - "to_param/1:909": { - "line": 909, - "guard": "is_binary(bin)", - "pattern": "bin", - "kind": "defp", - "end_line": 909, - "ast_sha": "a6ef8ff1e6d49bbb2526e189ac63dfe3c7959a3a00479d2d6645f5c7018916c5", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "77c8da775fa03fa721aae5347531df7608e5e7edc4bd9a2510d84c664fa90340", - "start_line": 909, - "name": "to_param", - "arity": 1 - }, - "validate_sigil_p!/1:400": { - "line": 400, - "guard": null, - "pattern": "[]", - "kind": "defp", - "end_line": 400, - "ast_sha": "50efa1e95ba3092268d96d48c2d0407a130e60f7bda6918fa3cb64eadf7833a0", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "1aaf7ce59b3bcebaa4da918b80ee71d0540768fb48b44e1b86bddafa5710ac7c", - "start_line": 400, - "name": "validate_sigil_p!", - "arity": 1 - }, - "compile_prefixes/2:1002": { - "line": 1002, - "guard": null, - "pattern": "path_prefixes, meta", - "kind": "defp", - "end_line": 1013, - "ast_sha": "4e1f062722956c99fef4fc518705d9436111de59133818280cda02e40b6ee3f7", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "7235146e16b78d2d8f1c1049ef64974f72b7ca2564ca59bd71a80c9f193b8c26", - "start_line": 1002, - "name": "compile_prefixes", - "arity": 2 - }, - "validate_sigil_p!/1:402": { - "line": 402, - "guard": null, - "pattern": "extra", - "kind": "defp", - "end_line": 403, - "ast_sha": "c3cee8f41843a92ce260d58539e1c72d2a20134d2dff5d4ed2f95f155d9eaa38", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "0cc81a96f40ad67f644873c1a47f004c42fb884a02de9b36238def3528505d74", - "start_line": 402, - "name": "validate_sigil_p!", - "arity": 1 - }, - "static_integrity/2:878": { - "line": 878, - "guard": null, - "pattern": "%Plug.Conn{private: %{phoenix_endpoint: endpoint}}, path", - "kind": "def", - "end_line": 879, - "ast_sha": "e5692521ab8bee838e8df7bf343df27cd1b6a0c5d3869d76472bb231de993f01", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "59aeba43c5a34bfa32e2f6de5075eee8a09b66d7c7febaa769b83d6d0bb67a6d", - "start_line": 878, - "name": "static_integrity", - "arity": 2 - }, - "attr!/2:1017": { - "line": 1017, - "guard": null, - "pattern": "%{function: nil}, _", - "kind": "defp", - "end_line": 1018, - "ast_sha": "42b47ae6dba0f45dc8ad98c2f4cb24649e78780d72c803124b68562c1302738a", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "24f1e7007f7ab2e736b249a94221fbbc1c781dc9d3fc36624229d5f3732e77dc", - "start_line": 1017, - "name": "attr!", - "arity": 2 - }, - "concat_url/2:651": { - "line": 651, - "guard": "is_binary(path)", - "pattern": "url, path", - "kind": "defp", - "end_line": 651, - "ast_sha": "358424e5720b2b89cb29fde27b9a6a1f8f5538f0d5885e85cd33be9d94a55586", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "26f58ad54c544c9c41d1e2f7eecaae7ea069c3002be89705355be4f683661c47", - "start_line": 651, - "name": "concat_url", - "arity": 2 - }, - "url/1:532": { - "line": 532, - "guard": null, - "pattern": "other", - "kind": "defmacro", - "end_line": 532, - "ast_sha": "85b5fc7397263ab4f9ed06122a10ffcea71e2ff7c620b36e2414f91d4c6975c9", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "1de80c3ea3a965c3b010ebecc7b270c362a41a1724221c52d510ab4f45d5a9f9", - "start_line": 532, - "name": "url", - "arity": 1 - }, - "static_url/2:596": { - "line": 596, - "guard": null, - "pattern": "%_{endpoint: endpoint}, path", - "kind": "def", - "end_line": 597, - "ast_sha": "170dab7ca873814e1bd6f1f24dca78b45f06833151aa7edae6afd25dc18b0901", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "1fa5edb2875c387c498bd5b5f9cfb8dcafaf049283fac21a06ac5f2d99a7a6f8", - "start_line": 596, - "name": "static_url", - "arity": 2 - }, - "url/1:523": { - "line": 523, - "guard": null, - "pattern": "{:sigil_p, _, [{:<<>>, _meta, _segments} = route, _]} = sigil_p", - "kind": "defmacro", - "end_line": 529, - "ast_sha": "f482053b161f9ea2a4a057a759b70649da7d4c4e65b21da3f99b701d786e2d0f", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "9cf85178b06b10a334405c2f29c5352166df291bbc78f198cbbe00ae38a9da75", - "start_line": 523, - "name": "url", - "arity": 1 - }, - "verify_segment/3:780": { - "line": 780, - "guard": null, - "pattern": "[<<\"?\"::binary, query::binary>>], _route, acc", - "kind": "defp", - "end_line": 781, - "ast_sha": "f42a238a85d90da5619bd9d0f87bd62e9295da91b2e5e0a5f0f65ff57afed604", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "2e194705b1bad49c4a98121fb857617acd2dac47d29679d9b7547560b98fafb2", - "start_line": 780, - "name": "verify_segment", - "arity": 3 - }, - "materialize_path/1:998": { - "line": 998, - "guard": null, - "pattern": "path", - "kind": "defp", - "end_line": 999, - "ast_sha": "96349d5e9917ebaf47ac31aac793c3391635313ce84f11c48d7287b9314fe65c", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "44fe0d44e89040c5abdecf6e493db1aaf4ff63be789daff925316cc49d894821", - "start_line": 998, - "name": "materialize_path", - "arity": 1 - }, - "static_url/2:600": { - "line": 600, - "guard": "is_atom(endpoint)", - "pattern": "endpoint, path", - "kind": "def", - "end_line": 601, - "ast_sha": "9a4dd50032f46e77c98d6a26ecb804250e4c243520238dca498480ae59462739", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "eece47a5cf6f8208a412d062f08a65bbcf1fb916f9012a97a8ccc0a34f3ca253", - "start_line": 600, - "name": "static_url", - "arity": 2 - }, - "inject_path/2:371": { - "line": 371, - "guard": null, - "pattern": "{%Phoenix.VerifiedRoutes{} = route, static?, _endpoint_ctx, _route_ast, path_ast, static_ast}, env", - "kind": "defp", - "end_line": 379, - "ast_sha": "1c28b8d1d00140bf1ed56b89613e1bf407081090d843e4a87f9706aa4ccffd43", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "fcc0f153737815c6915a1b15973a8214bb1d2328df9a923a46eedc346507d995", - "start_line": 371, - "name": "inject_path", - "arity": 2 - }, - "attr!/2:1032": { - "line": 1032, - "guard": null, - "pattern": "env, name", - "kind": "defp", - "end_line": 1033, - "ast_sha": "57f3d330e0e6eee41b33bf7bb346bb778a8fc918293a772ecf4ef352e7b3ac97", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "7dd4f8ddbbb74ad0744f28ff3bc5747789fa2f5d7209d473836143608580a6c3", - "start_line": 1032, - "name": "attr!", - "arity": 2 - }, - "__struct__/1:219": { - "line": 219, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 219, - "ast_sha": "475883802c714d67250991abdd9ab7892bedf7bd511444c9a5471740c5192ac2", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "6b0f19d7ab0dcc97db52ddf76d95137aab2a963a6fa18de787d94f2d28c6ff11", - "start_line": 219, - "name": "__struct__", - "arity": 1 - }, - "unverified_path/4:730": { - "line": 730, - "guard": null, - "pattern": "other, router, path, _params", - "kind": "def", - "end_line": 733, - "ast_sha": "aa6af246adf3d96da2c03c779f8bbdcc599ba00262fc59cdd6b0dc2725ad8ecb", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "62d6b5bb0f124227f30133ddfc20a095e25e1d0f043822319f93c856ee130f88", - "start_line": 730, - "name": "unverified_path", - "arity": 4 - }, - "static_integrity/2:886": { - "line": 886, - "guard": "is_atom(endpoint)", - "pattern": "endpoint, path", - "kind": "def", - "end_line": 887, - "ast_sha": "42bf544c0863fea9770afbeee941d9c565615570b11050c0a10096af5163f306", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "d1f27405e27577254ae84a5422cbcac885dbfa2ac0bc36eed91e3d18fd784a0b", - "start_line": 886, - "name": "static_integrity", - "arity": 2 - }, - "path_with_script/2:1061": { - "line": 1061, - "guard": null, - "pattern": "path, script", - "kind": "defp", - "end_line": 1061, - "ast_sha": "cc6b3b797aa992bd6b3e60f103b8c1fd51fc2f435ddbe1dfb5afb597514fd5e7", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "85e62c3e2c775a67b4c117061e12ad387a56dd06322b0d1552c685a80309b8fe", - "start_line": 1061, - "name": "path_with_script", - "arity": 2 - }, - "verify_segment/3:794": { - "line": 794, - "guard": "is_binary(prev)", - "pattern": "[{:\"::\", m1, [{{:., m2, [Kernel, :to_string]}, m3, [dynamic]}, {:binary, _, _} = bin]} | rest], route, [prev | _] = acc", - "kind": "defp", - "end_line": 804, - "ast_sha": "c80dd0cccfd7e8fd3ff79ed0883fcee8ba5673ae3a52db31aae85f9ee25f4538", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "ad7ffdf7585e09935ccc3826a5edcd725f5e0978f056ba529bd1d9fc3ae1e4e6", - "start_line": 794, - "name": "verify_segment", - "arity": 3 - }, - "__before_compile__/1:299": { - "line": 299, - "guard": null, - "pattern": "_env", - "kind": "defmacro", - "end_line": 306, - "ast_sha": "65bad7c7df5707b52710cf59097e8288493b316972d6004ff7d784f6168ef6e6", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "178fcbcc40532fc100ce74c612b763fcff2a4a5ffc3f13e617c1627900a1ccd6", - "start_line": 299, - "name": "__before_compile__", - "arity": 1 - }, - "verify_segment/3:789": { - "line": 789, - "guard": "is_binary(segment)", - "pattern": "[segment | _], route, _acc", - "kind": "defp", - "end_line": 791, - "ast_sha": "8ebd595004bfa720a2741926f9e911d70f9f43d86b01ecd6c6f4711b6ec6dd69", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "da3d3ace4d18776a09b5756c7433c6d4df89a0b0307e71e4147a0f175e2ac919", - "start_line": 789, - "name": "verify_segment", - "arity": 3 - }, - "unverified_path/4:726": { - "line": 726, - "guard": "is_atom(endpoint)", - "pattern": "endpoint, _router, path, params", - "kind": "def", - "end_line": 727, - "ast_sha": "aef6a17673bedc5dd56d2c433be91f7cf7c9f8bcfcd894f2653a57183154de6d", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "21c8e977219f17627ecf1d755dd970307779626a2eced3bc65a4d8943fea00e5", - "start_line": 726, - "name": "unverified_path", - "arity": 4 - }, - "path/3:433": { - "line": 433, - "guard": null, - "pattern": "conn_or_socket_or_endpoint_or_uri, router, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, extra]} = sigil_p", - "kind": "defmacro", - "end_line": 442, - "ast_sha": "72e3f98cc7f90d4e11973747c8234b0f3c385ef102b16197d65fb1dbb480711e", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "ab60b4f429317e7dfcb9ee3e396cd980f8d4321433df3e1a949b3d6ae6fd788d", - "start_line": 433, - "name": "path", - "arity": 3 - }, - "verify_segment/2:760": { - "line": 760, - "guard": null, - "pattern": "_, route", - "kind": "defp", - "end_line": 761, - "ast_sha": "7c8adea71836ce2672b6146a35c0c36e8032840da0a490b4c8d583a66094a6b1", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "85d418198cab54ea84f7a71882f3d959be33483ffb52e8c6b42b35ec49574862", - "start_line": 760, - "name": "verify_segment", - "arity": 2 - }, - "verify_segment/3:765": { - "line": 765, - "guard": null, - "pattern": "[\"/\" | rest], route, acc", - "kind": "defp", - "end_line": 765, - "ast_sha": "f426fae66ac0b58fe291aed0adb8f9db9de8add952de2325bca3544a269a503e", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "adbcdd5d9d67392e6c4dd870c2d1fd49937b9d787288ae5dcdde8d0b2b5aeba5", - "start_line": 765, - "name": "verify_segment", - "arity": 3 - }, - "maybe_sort_query/2:903": { - "line": 903, - "guard": null, - "pattern": "query_str, false", - "kind": "defp", - "end_line": 903, - "ast_sha": "fcecd77d337df8c8adf991ddba46ca7f23940578518531d374145a1afac9017c", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "6b5de0fb0ee730ab97c6166473381b8301d1dd66800bfa9458471359a388dfb9", - "start_line": 903, - "name": "maybe_sort_query", - "arity": 2 - }, - "guarded_unverified_url/3:641": { - "line": 641, - "guard": "is_atom(endpoint)", - "pattern": "endpoint, path, params", - "kind": "defp", - "end_line": 642, - "ast_sha": "fd7637e250dde05517dca969081264c02cb108140f1b60548df2a8883127d053", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "b49b9c7ae8a37fae09e991764ad7d739b002b26faa0c9f7d8fa78163930ff6cd", - "start_line": 641, - "name": "guarded_unverified_url", - "arity": 3 - }, - "__encode_segment__/1:743": { - "line": 743, - "guard": null, - "pattern": "data", - "kind": "def", - "end_line": 747, - "ast_sha": "db5b8ee10fd51341688a487326a921e4b8047ca157839ffe8bf6c5b8b1b4800d", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "8b8e6f2d93068e0b1a590eb65d38d76dfcf1ec45de8471b93ba7354b3781c3ab", - "start_line": 743, - "name": "__encode_segment__", - "arity": 1 - }, - "static_url/2:589": { - "line": 589, - "guard": null, - "pattern": "%Plug.Conn{private: private}, path", - "kind": "def", - "end_line": 592, - "ast_sha": "f20a10d6e6525f095a5a1a94084242f14f923c5962cde7240285b5cbb82c6875", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "85f56b40953ab0dbebaa53a38c87cd261f26268d46f84d32d8f7d5fb5461247f", - "start_line": 589, - "name": "static_url", - "arity": 2 - }, - "verify_query/3:815": { - "line": 815, - "guard": null, - "pattern": "[{:\"::\", m1, [{{:., m2, [Kernel, :to_string]}, m3, [arg]}, {:binary, _, _} = bin]} | rest], route, acc", - "kind": "defp", - "end_line": 833, - "ast_sha": "3d6135b15ff0aae3b1d0e7e44927a3af905e4c77cac8f7234184651c0d779c20", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "11cf0c65227e79040317fba8671af53891ef234b7d288549f37431c7ba4eb559", - "start_line": 815, - "name": "verify_query", - "arity": 3 - }, - "rewrite_path/4:954": { - "line": 954, - "guard": null, - "pattern": "route, endpoint, router, config", - "kind": "defp", - "end_line": 995, - "ast_sha": "559eddce3975aebf63a89a4fa2245fc67afe13f7f18ec02c5dcec18c9a80b92e", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "95441a0ed6304499e33cfdd40746ee15d12fc88a25e4152a4b27a3500ca28196", - "start_line": 954, - "name": "rewrite_path", - "arity": 4 - }, - "path/2:468": { - "line": 468, - "guard": null, - "pattern": "conn_or_socket_or_endpoint_or_uri, {:sigil_p, _, [{:<<>>, _meta, _segments} = route, extra]} = sigil_p", - "kind": "defmacro", - "end_line": 477, - "ast_sha": "234bcc347783d64ed03e1b1fe83eb76216e28734ffe3aaf993f7556eed7a5bdd", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "161e7c195bda8a4a1d7f6cd2a86b6979d052bd7e360cf7d2de661b949469fc84", - "start_line": 468, - "name": "path", - "arity": 2 - }, - "unverified_url/2:621": { - "line": 621, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 621, - "ast_sha": "b368d69c7d9c4c4cbd069353ce290b29be6e77dc864ea2ba15ead8a3483039aa", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "34261e720a2cf97517cca674f9b04bf5df94271dd1f728be4685ca70c9539122", - "start_line": 621, - "name": "unverified_url", - "arity": 2 - }, - "verify_query/3:842": { - "line": 842, - "guard": null, - "pattern": "[<<\"&\"::binary, _::binary>> = param | rest], route, acc", - "kind": "defp", - "end_line": 848, - "ast_sha": "f2dc71f5606ce2473f59713e2e7769b05ac6a76b1c2bf8547aec564ba5906642", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "bda827a3f45e71017c3732e8dd3842f24fd9b26618d6d7732ff6cce384c8ba22", - "start_line": 842, - "name": "verify_query", - "arity": 3 - }, - "inject_url/2:383": { - "line": 383, - "guard": null, - "pattern": "{%Phoenix.VerifiedRoutes{} = route, static?, endpoint_ctx, route_ast, path_ast, _static_ast}, env", - "kind": "defp", - "end_line": 395, - "ast_sha": "be2ee12036bf0180fa0e05946f89afc0d4108756c4c239869b96328b5391b761", - "source_file": "lib/phoenix/verified_routes.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/verified_routes.ex", - "source_sha": "c6165001c597bae9d10f022c4ee7f6e175e3b0ab9c6f578d22ffc462a9bbcbbd", - "start_line": 383, - "name": "inject_url", - "arity": 2 - } - }, - "Mix.Tasks.Phx.Gen.Json": { - "context_files/1:181": { - "line": 181, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: true} = context", - "kind": "defp", - "end_line": 182, - "ast_sha": "08e5af0af95b4ae237e06db824c74ba9d18fab30ffa137939e2db412b4640e6c", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "b8e10634616288e88627ee5a9cd69e46a3642b199a4844a8f1e358981d9287ec", - "start_line": 181, - "name": "context_files", - "arity": 1 - }, - "context_files/1:185": { - "line": 185, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: false}", - "kind": "defp", - "end_line": 185, - "ast_sha": "ad2cbe79da229551a16e109c305484cb1cebd315e5e6b44677876ecc0486a8e9", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "551fd264746e5095ff22eb41b8e345fe050ab94e430981cce5e59b87c1ebc8d3", - "start_line": 185, - "name": "context_files", - "arity": 1 - }, - "copy_new_files/3:208": { - "line": 208, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", - "kind": "def", - "end_line": 213, - "ast_sha": "e80492f8d42f38a04d4142af4fd674a377fcf2d4bc7c910c9a239fb0d5a4a953", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "09fbc38690a3a422ade53a0dbdfcea0a4da3d9f3eb29a4bff943686861859365", - "start_line": 208, - "name": "copy_new_files", - "arity": 3 - }, - "files_to_be_generated/1:190": { - "line": 190, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: context_app}", - "kind": "def", - "end_line": 203, - "ast_sha": "99755c2901c4ba78adb48b171586277917e034b4613812e477b9e06ba60d65ef", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "5bb596b6d830071d81ca417e3419538cc6efa7b2e52a90f56b9a85ebe670dd19", - "start_line": 190, - "name": "files_to_be_generated", - "arity": 1 - }, - "print_shell_instructions/1:217": { - "line": 217, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema, context_app: ctx_app} = context", - "kind": "def", - "end_line": 251, - "ast_sha": "2afeb9c71c24bb4c58beb193f785513b7cb0ad48379bee9b7f81c33da08a3617", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "1856a021e2ae5179db396198ece6b5c2daaa17e5adff585a2972347c6c5e81b0", - "start_line": 217, - "name": "print_shell_instructions", - "arity": 1 - }, - "run/1:122": { - "line": 122, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 171, - "ast_sha": "70c972e1a84c1e1c3e289731a0d80eccb9902cc87b7e823c204e4655a5ebc5b5", - "source_file": "lib/mix/tasks/phx.gen.json.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.json.ex", - "source_sha": "d471fe82a890711861ec3544b637e51dcadb04ae7e7c0fd5d471fb30c5a42865", - "start_line": 122, - "name": "run", - "arity": 1 - } - }, - "Phoenix.Param.BitString": { - "__impl__/1:74": { - "line": 74, - "guard": null, - "pattern": ":protocol", - "kind": "def", - "end_line": 74, - "ast_sha": "f4d626572854d1df4f32dc8054ce04e44005a9242efa7a0699c92ff5fac742ea", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "e5189dff34782443626d21e7baf075a52e34162ae2dec628696fd0eb21618632", - "start_line": 74, - "name": "__impl__", - "arity": 1 - }, - "to_param/1:75": { - "line": 75, - "guard": "is_binary(bin)", - "pattern": "bin", - "kind": "def", - "end_line": 75, - "ast_sha": "bd32b5e49ccf4d79a4bc0cc43fcee6b8f1c96d5c18bc46c445e758b2d40541d2", - "source_file": "lib/phoenix/param.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/param.ex", - "source_sha": "a545c9e051e728852d4e4cae25feab27eb39d5ab68185341436b42afe782280d", - "start_line": 75, - "name": "to_param", - "arity": 1 - } - }, - "Mix.Phoenix": { - "app_base/1:159": { - "line": 159, - "guard": null, - "pattern": "app", - "kind": "defp", - "end_line": 162, - "ast_sha": "f1db8d37a952cd17d68f258a5ecdfceecad9b239102aea768d4e8bc857cbb70b", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "63e64de731791509c63385ef7496b3d67a0857199751b3a959ca8dfe7fca91fd", - "start_line": 159, - "name": "app_base", - "arity": 1 - }, - "base/0:144": { - "line": 144, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 145, - "ast_sha": "3b256704e6abf10d712eaff8da852b74203465c695d856066eee0f6cc7572f7a", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "60f56f74eaa67c5e3ab03fc669836650a2bfc101cdbcbc24340962a070ca8f5a", - "start_line": 144, - "name": "base", - "arity": 0 - }, - "beam_to_module/1:183": { - "line": 183, - "guard": null, - "pattern": "path", - "kind": "defp", - "end_line": 184, - "ast_sha": "a7c6968c70bdc5dc6047664097cb8bd06c13247de89b6c076d6abc218f3a639b", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "8e86b1b3d98423c9e718fe79cea69b1cc10775ef1444825883dc630f718595f2", - "start_line": 183, - "name": "beam_to_module", - "arity": 1 - }, - "check_module_name_availability!/1:129": { - "line": 129, - "guard": null, - "pattern": "name", - "kind": "def", - "end_line": 133, - "ast_sha": "74a11de9b758f58971fd7695cd31de6af7f196cbf69087447ccfe818e58b0300", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "22ceb8a40cd33cd694a4eb19464dd8c7f309b3b9caf682d9135cf63549b1c55b", - "start_line": 129, - "name": "check_module_name_availability!", - "arity": 1 - }, - "context_app/0:256": { - "line": 256, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 261, - "ast_sha": "fdeffeeb5ca112741b9468e9a45404b9070b1f88a2c4c3582e5303ec588f3fc1", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "b4a83922b23b0f0877ad86f39e3ffc1da1be27752ebb7c77d5c19d706742cb2f", - "start_line": 256, - "name": "context_app", - "arity": 0 - }, - "context_app_path/2:223": { - "line": 223, - "guard": "is_atom(ctx_app)", - "pattern": "ctx_app, rel_path", - "kind": "def", - "end_line": 235, - "ast_sha": "cb97f7b27fe2a6ce0116c175b5edd3129d8c3b7df0cbadcfbe5152bd4f331e2a", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "cf95f18dd8d9b15599e04039b4429cf72237e82e83dd0183ef38f83a32677629", - "start_line": 223, - "name": "context_app_path", - "arity": 2 - }, - "context_base/1:155": { - "line": 155, - "guard": null, - "pattern": "ctx_app", - "kind": "def", - "end_line": 156, - "ast_sha": "4724f5a52e9eeca09932707d22393b4ec90df1d91094fa142f0813ba19a5037c", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "270aa1bc532604c6f5ed45f0215e2e7623bc9e68ef9a581673f0741a5639236f", - "start_line": 155, - "name": "context_base", - "arity": 1 - }, - "context_lib_path/2:242": { - "line": 242, - "guard": "is_atom(ctx_app)", - "pattern": "ctx_app, rel_path", - "kind": "def", - "end_line": 243, - "ast_sha": "92165fc0c821a029281fb08366c2b7cb19979ea753edbaff589826cafe4baac5", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "e43cf004a006ab3f11602bf8d77901efddd62a3b777968d200db8449272b7de4", - "start_line": 242, - "name": "context_lib_path", - "arity": 2 - }, - "context_test_path/2:249": { - "line": 249, - "guard": "is_atom(ctx_app)", - "pattern": "ctx_app, rel_path", - "kind": "def", - "end_line": 250, - "ast_sha": "1e1eeb8e76b1024a1f1859af4ee603ebd5116c4acbd751a231685e9015260019", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "fe7128a2420bf585f526aabe82b3029b511c40743af7d08601700ae778850307", - "start_line": 249, - "name": "context_test_path", - "arity": 2 - }, - "copy_from/4:29": { - "line": 29, - "guard": "is_list(mapping)", - "pattern": "apps, source_dir, binding, mapping", - "kind": "def", - "end_line": 56, - "ast_sha": "a07a0f2dbb73dee0f806e63128d5095ec6f2d0a12ad4f428b1162b5886ec7907", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "136123a9eae4c9f12ead65893f0452d274fcb62cd115914c548d85a2860c9a6b", - "start_line": 29, - "name": "copy_from", - "arity": 4 - }, - "ensure_live_view_compat!/1:388": { - "line": 388, - "guard": null, - "pattern": "generator_mod", - "kind": "def", - "end_line": 393, - "ast_sha": "04cfcb8226395848cab0a44030e66009535a15953b491ba82543c01767ed650f", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "f1db7c92b3f73050794d60e8f5a2db3d77b825ac95c9d14a7b9280349110f06c", - "start_line": 388, - "name": "ensure_live_view_compat!", - "arity": 1 - }, - "eval_from/3:11": { - "line": 11, - "guard": null, - "pattern": "apps, source_file_path, binding", - "kind": "def", - "end_line": 19, - "ast_sha": "1214b31f4a6a027adaeb180207d31bb572cb39f17f3ddbfb6596bb8e6afb862e", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "8a2240307e56e482ee314a3e30ce907e6c44d6aeb2dd411ca5de6306eed00b10", - "start_line": 11, - "name": "eval_from", - "arity": 3 - }, - "fetch_context_app/1:278": { - "line": 278, - "guard": null, - "pattern": "this_otp_app", - "kind": "defp", - "end_line": 307, - "ast_sha": "81f94ca2fb301c1151e65d44d365e9554b9712248e758b92dcff66a765dc3c0b", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "ff889e48f587fd7128774ec6d34db9127868165cc32180a7ecb9f7d57a500664", - "start_line": 278, - "name": "fetch_context_app", - "arity": 1 - }, - "generator_paths/0:193": { - "line": 193, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 193, - "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "e5c17571418d5e5e08ffa13b036e122c84a76d25e7acf6f6fb9e3226fc83cb71", - "start_line": 193, - "name": "generator_paths", - "arity": 0 - }, - "in_umbrella?/1:200": { - "line": 200, - "guard": null, - "pattern": "app_path", - "kind": "def", - "end_line": 204, - "ast_sha": "ae2338907b323fba4094fdd072d00bc7797efcbfc815a46edc8072da98fb5bc3", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "b37f76ff1f891f72dd56e8ec54fbd5ce9de304fa66fcc19605bd7dfe515b94f8", - "start_line": 200, - "name": "in_umbrella?", - "arity": 1 - }, - "inflect/1:104": { - "line": 104, - "guard": null, - "pattern": "singular", - "kind": "def", - "end_line": 122, - "ast_sha": "5ac6eae93ca0ae725b23e31bcf6df485f8680ecd0bdb6c9f078f10ef9e9e6df6", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "cfcd3a1453d58fa8dbf51779336c891b281b999f8452b96106465064d199aae3", - "start_line": 104, - "name": "inflect", - "arity": 1 - }, - "maybe_eex_gettext/2:426": { - "line": 426, - "guard": null, - "pattern": "message, gettext?", - "kind": "defp", - "end_line": 430, - "ast_sha": "16b94429a17d3aed268389c6cd2803f78be402b65c70cc9c64ab557eae06669f", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "3f6320757eb15ace6fdafeb622e9fb9160a3f06ebde9bdbbcec2cbc43a9ab2eb", - "start_line": 426, - "name": "maybe_eex_gettext", - "arity": 2 - }, - "maybe_heex_attr_gettext/2:408": { - "line": 408, - "guard": null, - "pattern": "message, gettext?", - "kind": "defp", - "end_line": 412, - "ast_sha": "9ae782618d093aa0898c5d92dff1cbb59ae4983a041f264e2dcfa0ce3efc447a", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "1a9f2d27c9faac7c22055fb5988fa024c4c3fc6233b105cea62e6b9720aa201a", - "start_line": 408, - "name": "maybe_heex_attr_gettext", - "arity": 2 - }, - "mix_app_path/2:311": { - "line": 311, - "guard": null, - "pattern": "app, this_otp_app", - "kind": "defp", - "end_line": 331, - "ast_sha": "1f26f4d8f54358013eb8a90c220a85e20f788e8e7e8857d63dd08e7a860e3543", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "b1755ecfaf4cbf806e18df2b154105671ce4f5cfc51ad31e934630117ffd4d4f", - "start_line": 311, - "name": "mix_app_path", - "arity": 2 - }, - "modules/0:176": { - "line": 176, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 180, - "ast_sha": "18262def4d3b280822f26ce1e0afd12894e2a57c196b6849e1119d1a0edc15db", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "4007d5ebff0c71cc1ae2ff5e20a7c6155c72e1675d552575acf468185d103193", - "start_line": 176, - "name": "modules", - "arity": 0 - }, - "otp_app/0:169": { - "line": 169, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 170, - "ast_sha": "4c9ab3738894222475fe51a136c497227f1c1a79cf232a46d4bd40f3357508d9", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "7f3b5bd5e1e64c833938c67e1076545c07e6cf4ce760b207de3514aff8855489", - "start_line": 169, - "name": "otp_app", - "arity": 0 - }, - "prepend_newline/1:381": { - "line": 381, - "guard": null, - "pattern": "string", - "kind": "def", - "end_line": 382, - "ast_sha": "544535c6eacb56d67876d3b7ac5a87edc66b45f81428608e13b6516ae4d0f1f5", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "7970ceb5faf1d41646917ca09c410f1bdafbc1d03bb246a74effb9b912f4e481", - "start_line": 381, - "name": "prepend_newline", - "arity": 1 - }, - "prompt_for_conflicts/1:340": { - "line": 340, - "guard": null, - "pattern": "generator_files", - "kind": "def", - "end_line": 361, - "ast_sha": "de64a691ccf69ca4e9f8e8fa96d8b79cd3f0333af74ad3410bdc2c7a1f31a971", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "9d71182a7bbee0073f4f87c303f821c626bb348cf2a0d2cefae36696a40febbc", - "start_line": 340, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "to_app_source/2:62": { - "line": 62, - "guard": "is_binary(path)", - "pattern": "path, source_dir", - "kind": "defp", - "end_line": 63, - "ast_sha": "fe465936bffa922f044e69d236e0f9f40ed3cafc6ed4b106b2eab4862cef5e77", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "3d1ca1cf6979bba11816f92b2bd162eee8a0a050177e289a4fa4849d1465b7e0", - "start_line": 62, - "name": "to_app_source", - "arity": 2 - }, - "to_app_source/2:65": { - "line": 65, - "guard": "is_atom(app)", - "pattern": "app, source_dir", - "kind": "defp", - "end_line": 66, - "ast_sha": "46f18f191a6a250644236b3cbc257e61c32f29f2dbe19794d3595951d78530bd", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "44ca1365cf523abd97d73b07d63f32281426b0d02085806522f1c535c84386be", - "start_line": 65, - "name": "to_app_source", - "arity": 2 - }, - "to_text/1:377": { - "line": 377, - "guard": null, - "pattern": "data", - "kind": "def", - "end_line": 378, - "ast_sha": "fe2da53c644980e24e8c2fa6d2d1d4961f2b68f658322cc7f76124ecf57b72d3", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "f695e7edc75d016604f02f49d5626f0bd50ecfe36013b48a31ddf5c487c92d81", - "start_line": 377, - "name": "to_text", - "arity": 1 - }, - "web_module/1:369": { - "line": 369, - "guard": null, - "pattern": "base", - "kind": "def", - "end_line": 373, - "ast_sha": "9b0cbbb7580d2abdc440403a0443cdd3e6ea5bb6d167471ef8b671ca0a2459a6", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "64321f381c0c178570d1ca0b2fc7a56ae7c65e27506d79030525ba44d69adb4a", - "start_line": 369, - "name": "web_module", - "arity": 1 - }, - "web_path/1:210": { - "line": 210, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 210, - "ast_sha": "83b68980fac0d4765f90a093aa89b7b07a667d058ec886b15720b57bf966f425", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "cdcd028359aea62dd6a0e91b1c82a04912474ca939927dc7c95bd2ce34e54f44", - "start_line": 210, - "name": "web_path", - "arity": 1 - }, - "web_path/2:210": { - "line": 210, - "guard": "is_atom(ctx_app)", - "pattern": "ctx_app, rel_path", - "kind": "def", - "end_line": 216, - "ast_sha": "c6186a5e0983d69be88f30f4b4be6827ba65dd874ee3e2befc9ebf5d9b0ffeed", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "b53f7a66b8253cdf4e320367bb258b32996b81544d0e4762df24d6d765149dd0", - "start_line": 210, - "name": "web_path", - "arity": 2 - }, - "web_test_path/1:268": { - "line": 268, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 268, - "ast_sha": "858f360365ca4991a2c4607fdbb3a0832ceb818ac4b88b6bffb79b24649c9a44", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "0cd82657a14b1cc6e0132c33ff26c92ae7bbe763bf395b79d8d3248aa967fe5b", - "start_line": 268, - "name": "web_test_path", - "arity": 1 - }, - "web_test_path/2:268": { - "line": 268, - "guard": "is_atom(ctx_app)", - "pattern": "ctx_app, rel_path", - "kind": "def", - "end_line": 274, - "ast_sha": "577f15653fc682e9ea5a9b6e4240e5db4097643b3c995ac290eb2de70fc84be8", - "source_file": "lib/mix/phoenix.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix.ex", - "source_sha": "725016881915367394bfa87eb280a4bad00fad3dffef4592c8e06ccb72f381f2", - "start_line": 268, - "name": "web_test_path", - "arity": 2 - } - }, - "Mix.Phoenix.Context": { - "file_count/1:84": { - "line": 84, - "guard": null, - "pattern": "%Mix.Phoenix.Context{dir: dir}", - "kind": "def", - "end_line": 88, - "ast_sha": "f42fe19dcac0c043addb81461cb511cbad635e4f9f2668fdcad99ed2aeed3d5c", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "f10897aa34087b150824631ad992f2d5267d0e46bf057218829392bd951df5a0", - "start_line": 84, - "name": "file_count", - "arity": 1 - }, - "function_count/1:70": { - "line": 70, - "guard": null, - "pattern": "%Mix.Phoenix.Context{file: file}", - "kind": "def", - "end_line": 81, - "ast_sha": "2f4a102a98eac99ed9d90175b2b93ae33e2daa3832964ef3270daeb678004856", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "43aaff34a4ea5c7ac16a87aef5367d6e0f1b7f81f69984d2896dcc84c98c208c", - "start_line": 70, - "name": "function_count", - "arity": 1 - }, - "new/2:26": { - "line": 26, - "guard": null, - "pattern": "context_name, opts", - "kind": "def", - "end_line": 27, - "ast_sha": "92b4cf8856c94d635b935f083a79b22a66ae91f7bf22bc1f94fa83733f8ca398", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "4ed27cf2c38de19a4083924f23d385e32715d69b297b236cfaa9d984e80a1fac", - "start_line": 26, - "name": "new", - "arity": 2 - }, - "new/3:30": { - "line": 30, - "guard": null, - "pattern": "context_name, %Mix.Phoenix.Schema{} = schema, opts", - "kind": "def", - "end_line": 60, - "ast_sha": "8912e498b9ff00444cd76f957b686349eaef6a13162f89fc97ed3ff91c3d1963", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "55943d13330670fa6acbbc618e0818a0b6bdbe32f027d7d3a25e1d71c47a9ba8", - "start_line": 30, - "name": "new", - "arity": 3 - }, - "pre_existing?/1:64": { - "line": 64, - "guard": null, - "pattern": "%Mix.Phoenix.Context{file: file}", - "kind": "def", - "end_line": 64, - "ast_sha": "67ac52d54abc7c0cdd8ff2f8bcaeddbd51eb371152a4eb909bff21756bc0bd76", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "88badffed413fd62f1881487dc2b2c05dbcb38634dc4ca820ba469d48f86914c", - "start_line": 64, - "name": "pre_existing?", - "arity": 1 - }, - "pre_existing_test_fixtures?/1:68": { - "line": 68, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_fixtures_file: file}", - "kind": "def", - "end_line": 68, - "ast_sha": "c6dd00dcf15e167c4821737763001ca7842659e9a37de1de6fe68a192916c58c", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "dae4ca3f040325ef007b162166c1e4d52f8235330d63f96c4b7db6a2beee8e2f", - "start_line": 68, - "name": "pre_existing_test_fixtures?", - "arity": 1 - }, - "pre_existing_tests?/1:66": { - "line": 66, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_file: file}", - "kind": "def", - "end_line": 66, - "ast_sha": "28d04e76d472045e9e4b91aa8d396f7b0817cf68da4e399dbdf2bff86c9e3030", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "d549de0ab0de850aa8495b56072af775844bd16fbe6bad4067b4d6cd7b68cab9", - "start_line": 66, - "name": "pre_existing_tests?", - "arity": 1 - }, - "valid?/1:22": { - "line": 22, - "guard": null, - "pattern": "context", - "kind": "def", - "end_line": 23, - "ast_sha": "b3b7d4de52e6a82a51bcd1d17ed349604b1afe374bdbdedcf069ca9eb4bc2cb2", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "ec65fc16f62db1b0c9c22ff34ba28d2ae429607e5a73ff5e39d4f84a9f197f01", - "start_line": 22, - "name": "valid?", - "arity": 1 - }, - "web_module/0:91": { - "line": 91, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 101, - "ast_sha": "ff6b36430b5656cf41d5d8bd6923508e194ce0867811a4e4236de4b2b871154c", - "source_file": "lib/mix/phoenix/context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/phoenix/context.ex", - "source_sha": "61c8245b2732da754f9b929c7b4d4264a1dcda196418ffe94aff28517590bc31", - "start_line": 91, - "name": "web_module", - "arity": 0 - } - }, - "Mix.Tasks.Phx.Gen.Context": { - "build/1:145": { - "line": 145, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 145, - "ast_sha": "0799ce3d1f55a6b723fbfb8ec68d13806532b1e9a592ca0a0aa6f58dd1444531", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "b587df70a76d18287d29b4122350c06676205e48db52cdf395ed0d959f93efe9", - "start_line": 145, - "name": "build", - "arity": 1 - }, - "build/2:145": { - "line": 145, - "guard": null, - "pattern": "args, opts", - "kind": "def", - "end_line": 157, - "ast_sha": "2d34ddddd3170a412972ef3cb9acfc56770c1fdd376e1bb8198d0f86ae2a9f39", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "70e7d1a488efd5588bfe82092d9e4c96b5077ffe689b55f2c512a40f818bb4e0", - "start_line": 145, - "name": "build", - "arity": 2 - }, - "copy_new_files/3:187": { - "line": 187, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema} = context, paths, binding", - "kind": "def", - "end_line": 193, - "ast_sha": "85e827c89ab95c5cdac7d5aacf1f11cfa22814e31a313d31e5072b8de91cfa88", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "c86a9b86c6f3d34795963284c776296c7eb540d477238955c0fb270962714a86", - "start_line": 187, - "name": "copy_new_files", - "arity": 3 - }, - "ensure_context_file_exists/3:197": { - "line": 197, - "guard": null, - "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", - "kind": "def", - "end_line": 201, - "ast_sha": "74111f1d9aed09e6246223c54a05eab94a85a8743ef72c890795ac42e5085870", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "7a2a703a9153c447080ea92baa16e1316ea549dd0c3ed02294b8c597033f7184", - "start_line": 197, - "name": "ensure_context_file_exists", - "arity": 3 - }, - "ensure_test_file_exists/3:222": { - "line": 222, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", - "kind": "def", - "end_line": 226, - "ast_sha": "296a06230012831524d0d24674cc3346096800160f909ba68b955588eab35ff0", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "5a6daf026469468506af0c82499494d398ef0f0b5c7c7e542ec05aa6de29b641", - "start_line": 222, - "name": "ensure_test_file_exists", - "arity": 3 - }, - "ensure_test_fixtures_file_exists/3:247": { - "line": 247, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", - "kind": "def", - "end_line": 255, - "ast_sha": "47743768619087b8695ed6a8e59064b9fc66318f7a307aaa1843b911a51bed23", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "0d7975715cf40f1c7e94f198a2f07027e02ce0b74cc07229ae1166c20f03629c", - "start_line": 247, - "name": "ensure_test_fixtures_file_exists", - "arity": 3 - }, - "files_to_be_generated/1:178": { - "line": 178, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema}", - "kind": "def", - "end_line": 180, - "ast_sha": "e007e66bcf44dea5ebd7f0c4d7b428579fe0f203036697e1b5e460ce28fc8854", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "036e7a9813b4594172ed2e965234827c1593dbc7cc9c22e6312b169e33ed3e9d", - "start_line": 178, - "name": "files_to_be_generated", - "arity": 1 - }, - "indent/2:297": { - "line": 297, - "guard": null, - "pattern": "string, spaces", - "kind": "defp", - "end_line": 306, - "ast_sha": "590e92133e87b75da0f7fdd7be1a814f8b3b05a6fe53318f24cbaa1e1933891e", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "c7606eb96c17c56661fbda2cd72f01c8634ef02562e9c1d2985d50bb615f586e", - "start_line": 297, - "name": "indent", - "arity": 2 - }, - "inject_eex_before_final_end/3:311": { - "line": 311, - "guard": null, - "pattern": "content_to_inject, file_path, binding", - "kind": "defp", - "end_line": 325, - "ast_sha": "ef1d47be16b9757c94c28c41e99bd709dcfec6cf5899ea4e1cbf7f2c9f5da431", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "c26df9cedcd5bbb549d4fd18002a4b2bb739e860e2b833f41dbc056ceaf0f525", - "start_line": 311, - "name": "inject_eex_before_final_end", - "arity": 3 - }, - "inject_schema_access/3:206": { - "line": 206, - "guard": null, - "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", - "kind": "defp", - "end_line": 214, - "ast_sha": "77a6bed40a5696b98a0459e7346f6e73f9e7410c8288b6d7905b9aefad7aac73", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "268ea9f81b22bd4b4e5b5b216550b4138905f7049850b0638b07709ca4e8284b", - "start_line": 206, - "name": "inject_schema_access", - "arity": 3 - }, - "inject_test_fixture/3:260": { - "line": 260, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", - "kind": "defp", - "end_line": 272, - "ast_sha": "08d52794de4022ae7951ae3d120219ee77a68276259c90be6f8e9fe5d8f68dab", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "6caad17f91e82ea1a49863973e079c57d781dd4d3eeae30e98dbabdf44c18624", - "start_line": 260, - "name": "inject_test_fixture", - "arity": 3 - }, - "inject_tests/3:231": { - "line": 231, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", - "kind": "defp", - "end_line": 243, - "ast_sha": "9c892396e26a865aa69e31a730a008b86dec161743bbd9576d93b48896c48e66", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "733068849692e90b53cb2a473297ddbe3c770a97ed99d5da815de8311cc44762", - "start_line": 231, - "name": "inject_tests", - "arity": 3 - }, - "maybe_print_unimplemented_fixture_functions/1:275": { - "line": 275, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 292, - "ast_sha": "2bbd03af91b4ac97d88ab92e24b04e9151ecddfa6213d31c289aa1afde5f7b06", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "6d622ce0a01b5a2f12923c0c9ae7b6e49f93188a68e47a65ea71d83b47f5414d", - "start_line": 275, - "name": "maybe_print_unimplemented_fixture_functions", - "arity": 1 - }, - "merge_with_existing_context?/1:453": { - "line": 453, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 476, - "ast_sha": "aabb69f52db446f7ae857e23bf156cb94a34fe2861519a5c1d7e583f979991cd", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "126bf3edd122c7c398c074140f45f975cd6c321a5ad0fedebb2b422cfd91f97f", - "start_line": 453, - "name": "merge_with_existing_context?", - "arity": 1 - }, - "parse_opts/1:160": { - "line": 160, - "guard": null, - "pattern": "args", - "kind": "defp", - "end_line": 168, - "ast_sha": "d7945fb06298f8c7ffc87afccf273d55330129c3ade2529b6244655c6ca34ac9", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "b8123a54ec4f72f3259f14c695c1ff2f31703846c6de7447ad00611f6af54ed9", - "start_line": 160, - "name": "parse_opts", - "arity": 1 - }, - "print_shell_instructions/1:330": { - "line": 330, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema}", - "kind": "def", - "end_line": 332, - "ast_sha": "c6662cdb85d4811bda42fb0728ee1d6f4a0a681161037a46bccb6c4abd9bff22", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "8c67e261d2d3d9bbb7261ee1f0a574e4b893d1f1201172d7a3c154fdffd5b703", - "start_line": 330, - "name": "print_shell_instructions", - "arity": 1 - }, - "prompt_for_code_injection/1:445": { - "line": 445, - "guard": null, - "pattern": "%Mix.Phoenix.Context{generate?: false}", - "kind": "def", - "end_line": 445, - "ast_sha": "84607d6c4899c7e56026195e909b4ffe07cace83c4410a1ccf458b0701040d15", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "3f15bf405c07607f33a83b715a0b77b7770329c121ae41918ce6cf660cbf80c1", - "start_line": 445, - "name": "prompt_for_code_injection", - "arity": 1 - }, - "prompt_for_code_injection/1:447": { - "line": 447, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "def", - "end_line": 449, - "ast_sha": "3d2ba51c2e1734fc19f487e10642086caf4ff5be10a503ec98d059043c898f4b", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "413fa96f2f3af06c3b92bbd84badaee3b2b05351b74edba148f39ca2bb4d6e6d", - "start_line": 447, - "name": "prompt_for_code_injection", - "arity": 1 - }, - "prompt_for_conflicts/1:138": { - "line": 138, - "guard": null, - "pattern": "context", - "kind": "defp", - "end_line": 141, - "ast_sha": "bdb16733bd5f4e623e7ff670421478b975f35e6929f6734cdf134e264001ff47", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "b37e08e41ebe1d8327bba055336126cf15772dc431c6ca55e3ba694a48c5a27a", - "start_line": 138, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "put_context_app/2:171": { - "line": 171, - "guard": null, - "pattern": "opts, nil", - "kind": "defp", - "end_line": 171, - "ast_sha": "97d00bffead5d8c18c16a7aea61317f7237f83186a9a19744ca58247f44ec6d6", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "7c836438fa299b4240e14dca20bccf5849c00f7d1b75fa5bffe15b384f8f9061", - "start_line": 171, - "name": "put_context_app", - "arity": 2 - }, - "put_context_app/2:173": { - "line": 173, - "guard": null, - "pattern": "opts, string", - "kind": "defp", - "end_line": 174, - "ast_sha": "874ac9aab75cfa76e3340b444da1547cf7af147a21d04d93ab6ef34af30b02e1", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "d0a101e376a88c20c75aa27d422fa916c5d99698e3b9d0721049fb56a812913b", - "start_line": 173, - "name": "put_context_app", - "arity": 2 - }, - "raise_with_help/1:423": { - "line": 423, - "guard": null, - "pattern": "msg", - "kind": "def", - "end_line": 425, - "ast_sha": "80c89afac535d39230f9a18b436dce7b92af9e05b11b2c6cb76e3238e8b7728e", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "5f7c10c313caa3d8a4aeba153a02ba0759c87d1f7164619a783b2ee39689ec7f", - "start_line": 423, - "name": "raise_with_help", - "arity": 1 - }, - "run/1:112": { - "line": 112, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 135, - "ast_sha": "06fb3783f2d5f59f0fd15a5c60b5273cb28a54476e111bdc71a90fc144dd2fc5", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "42c1ac42b3355208120cd1147ed950ec176a28b6a71d34029a5d1a5ff8093ccd", - "start_line": 112, - "name": "run", - "arity": 1 - }, - "schema_access_template/1:338": { - "line": 338, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema}", - "kind": "defp", - "end_line": 349, - "ast_sha": "b506d197c899ca8bbad89bf92ad993002b27397b9301801454dcd0ef0ef2d2bf", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "dcebdc07b0c6e8cea42bf99df1ee5c4427eb19ddf211fe9c710dc881cafa007d", - "start_line": 338, - "name": "schema_access_template", - "arity": 1 - }, - "singularize/2:480": { - "line": 480, - "guard": null, - "pattern": "1, plural", - "kind": "defp", - "end_line": 480, - "ast_sha": "c205a443ba79e93ea64d30233e45ea81a1d58787185cc5807dc17808dd884297", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "7e139b39740c28b370bc3bd64809a73e27a72ad064c27c162699656fa6e8ec06", - "start_line": 480, - "name": "singularize", - "arity": 2 - }, - "singularize/2:481": { - "line": 481, - "guard": null, - "pattern": "amount, plural", - "kind": "defp", - "end_line": 481, - "ast_sha": "7710d0c6148d214693dc65f6249e9ea01bc76ffb30cf0f8721b2d024ff3cc91d", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "9c04b845fe2b8621c657ef5f3b7b4e8292a2e03059612e7478d025513d049260", - "start_line": 481, - "name": "singularize", - "arity": 2 - }, - "validate_args!/3:354": { - "line": 354, - "guard": null, - "pattern": "[maybe_context_name, schema_name_or_plural, plural_or_first_attr | schema_args], optional, help", - "kind": "defp", - "end_line": 414, - "ast_sha": "8650faa9936e3be738964837bf8d5ec4522a80c8ab99679fa158da5a97b7883c", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "f449a8397ada78a559d099d85a817b6987a0878f3506a71bcb9e515908e9f183", - "start_line": 354, - "name": "validate_args!", - "arity": 3 - }, - "validate_args!/3:418": { - "line": 418, - "guard": null, - "pattern": "_, _, help", - "kind": "defp", - "end_line": 419, - "ast_sha": "9e123290bc6df2f5d70840d41e9f504b38919192546e047da938caa9d8368902", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "b268709a37013321d79bf8d315de480b8ed7ce2dbfb21746f67477830ad21a1f", - "start_line": 418, - "name": "validate_args!", - "arity": 3 - }, - "write_file/2:217": { - "line": 217, - "guard": null, - "pattern": "content, file", - "kind": "defp", - "end_line": 218, - "ast_sha": "ba947015abd9bcb81b56a619de387926c984cf8f48f12339c2ad5ad26a6aa770", - "source_file": "lib/mix/tasks/phx.gen.context.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.context.ex", - "source_sha": "6c52e1d76cb17916a120f205049f0892b4f18681feefb06f2a403c02f17e253d", - "start_line": 217, - "name": "write_file", - "arity": 2 - } - }, - "Phoenix.Token": { - "decrypt/3:244": { - "line": 244, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 244, - "ast_sha": "a8ef2af15bc5b42d6892274ca90ef1f5426fab435ca56b74742675d34c4dcd9c", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "babdf23300fc4a6a6e6510c11fc9882ded5975d74c06fd882015a03a9e94fdbe", - "start_line": 244, - "name": "decrypt", - "arity": 3 - }, - "decrypt/4:244": { - "line": 244, - "guard": "is_binary(secret)", - "pattern": "context, secret, token, opts", - "kind": "def", - "end_line": 247, - "ast_sha": "37437803101785e59dae8d6a35e9642d65d737c9adbc5e829fbc213d14a1d0df", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "75463726383d1a66a8633ad2a2c7d776bda38abf07fc4f4cd366ae9ac0d2ac28", - "start_line": 244, - "name": "decrypt", - "arity": 4 - }, - "encrypt/3:159": { - "line": 159, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 159, - "ast_sha": "0e16fbbb3fb6bf0e093149a247a0283b32c5e02ad11d346418c08a1d0763371c", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "539c1628c76c6d324e73ec43ffac14ef19f780a976d8fbd14473f95a91d32bc1", - "start_line": 159, - "name": "encrypt", - "arity": 3 - }, - "encrypt/4:159": { - "line": 159, - "guard": "is_binary(secret)", - "pattern": "context, secret, data, opts", - "kind": "def", - "end_line": 162, - "ast_sha": "710cd615fb654fa966cba35a23b7a09a8fa25e9b68fdc45dbb6b3f3e6875f060", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "69c0720a773ac140196696ea28fd61abe68eaf833d97f1f2f72319226bdee60f", - "start_line": 159, - "name": "encrypt", - "arity": 4 - }, - "get_endpoint_key_base/1:264": { - "line": 264, - "guard": null, - "pattern": "endpoint", - "kind": "defp", - "end_line": 267, - "ast_sha": "c2eca5589311219e65e778884a4b88592d878d967ce29c6c4d6b68e94d1d786e", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "977e6ac94c6493696ede0aa0d86715d048cb8a8d722dc9e06936b57a179ccc72", - "start_line": 264, - "name": "get_endpoint_key_base", - "arity": 1 - }, - "get_key_base/1:252": { - "line": 252, - "guard": null, - "pattern": "%Plug.Conn{} = conn", - "kind": "defp", - "end_line": 253, - "ast_sha": "5008a20c4515179cf0bba3393fcfb1745d1e03d39272ed2e744cf50bd2221659", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "eeb3f9bc48b32182209f4eef3af9d3c32bb2ad0da08555f7a983f234ad860472", - "start_line": 252, - "name": "get_key_base", - "arity": 1 - }, - "get_key_base/1:255": { - "line": 255, - "guard": null, - "pattern": "%_{endpoint: endpoint}", - "kind": "defp", - "end_line": 256, - "ast_sha": "165477dec0b3e0a63c0661924518100b358b833e34affade066eb495720e161f", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "df87a6bd56205db0f58adfabf9f6062ab0d5528ba233bee8e44398ac298538f8", - "start_line": 255, - "name": "get_key_base", - "arity": 1 - }, - "get_key_base/1:258": { - "line": 258, - "guard": "is_atom(endpoint)", - "pattern": "endpoint", - "kind": "defp", - "end_line": 259, - "ast_sha": "a3a9e4e70087080678fc9071c051aaf0d0397fa6029dfa33b9af05405bacef81", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "2a8eee5a9c2269982ac63b46455dcf5df7938e40bd29b8bfea4990c10d57d93c", - "start_line": 258, - "name": "get_key_base", - "arity": 1 - }, - "get_key_base/1:261": { - "line": 261, - "guard": "is_binary(string) and byte_size(string) >= 20", - "pattern": "string", - "kind": "defp", - "end_line": 262, - "ast_sha": "a4f827a384ff1650ca35f3785e36d7242b1f7fa21c4bafb7827a458556e6a254", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "51711452f25ce864d803f915a9bdd7e10e230305f3fd29cb38c03a5bc83ea58f", - "start_line": 261, - "name": "get_key_base", - "arity": 1 - }, - "sign/3:133": { - "line": 133, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 133, - "ast_sha": "756433e8022dd4a2ca08cddeb4bd423b73d3d2d806ee96ea6416b3e5d5d93ee4", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "0f286dd0ff32bc2498e4544b84f1dd007dd0e337b4b228cf0b7f15326a8da7f2", - "start_line": 133, - "name": "sign", - "arity": 3 - }, - "sign/4:133": { - "line": 133, - "guard": "is_binary(salt)", - "pattern": "context, salt, data, opts", - "kind": "def", - "end_line": 136, - "ast_sha": "63f45948292a1019cf76b58463f64d8d72dbb578d02e22b1732e731fbd9bbf42", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "1d67ff6e4315ceba6bb9f20b0cd34ae551b467ab5dfda37429186446df738f6a", - "start_line": 133, - "name": "sign", - "arity": 4 - }, - "verify/3:220": { - "line": 220, - "guard": null, - "pattern": "x0, x1, x2", - "kind": "def", - "end_line": 220, - "ast_sha": "7e7cb4bf462b45803283fa18c0c7775bedd7f6903cdf37f4426b73023cc7acc4", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "5380d3fa6a2b1f6189115c62f30324b67d157ab45f6e5ab16ee90c4ec3cc01a3", - "start_line": 220, - "name": "verify", - "arity": 3 - }, - "verify/4:220": { - "line": 220, - "guard": "is_binary(salt)", - "pattern": "context, salt, token, opts", - "kind": "def", - "end_line": 223, - "ast_sha": "259bb8e2d7cb192e98afaf7431297d99f1b8e11706e5dcad3fdf0d43da5e00b7", - "source_file": "lib/phoenix/token.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/token.ex", - "source_sha": "514bb74124b35e0eb752137fe5c0aa24c7c694faccbb74444e2a6117edaea580", - "start_line": 220, - "name": "verify", - "arity": 4 - } - }, - "Phoenix.Router.Scope": { - "update_attribute/3:299": { - "line": 299, - "guard": null, - "pattern": "module, attr, fun", - "kind": "defp", - "end_line": 300, - "ast_sha": "2340fbb7a55c23a8ef2116e158f9f300fcf95f415124ea173819fe459792a5d6", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "384e6712c615224092989c81abe1a888e8348c0569e594595c93f1d4cfb6af2f", - "start_line": 299, - "name": "update_attribute", - "arity": 3 - }, - "pop/1:223": { - "line": 223, - "guard": null, - "pattern": "module", - "kind": "def", - "end_line": 226, - "ast_sha": "307153ab1ef0c62cdb416e0a8ba3fd760f30fe784cd0b9977bee8bc8b1d87ad9", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "8317ba7d753bb11c4b471119b3e6f7a3fd67bf14a77e01c79c548d72672b076d", - "start_line": 223, - "name": "pop", - "arity": 1 - }, - "pipeline/2:114": { - "line": 114, - "guard": "is_atom(pipe)", - "pattern": "module, pipe", - "kind": "def", - "end_line": 115, - "ast_sha": "103073a29e2fef35c9e6468b6c35130037554c90f267b31d0b593f34e430a982", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "b2a86fac1c2fbf15979f1fb161048101fca2dbb53e76da0c0517a101439e2735", - "start_line": 114, - "name": "pipeline", - "arity": 2 - }, - "validate_hosts!/1:194": { - "line": 194, - "guard": null, - "pattern": "nil", - "kind": "defp", - "end_line": 194, - "ast_sha": "410d7b6b887436685793fbe282c1e142752de50dd78b8e1c5709a32e7e55842a", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "ec0ba4f3e1ca108f09de5d705ccef7862b1396c3f9734021e40b26976a9bb6ad", - "start_line": 194, - "name": "validate_hosts!", - "arity": 1 - }, - "full_path/2:240": { - "line": 240, - "guard": null, - "pattern": "module, path", - "kind": "def", - "end_line": 247, - "ast_sha": "f2c8c771e41f8a90469857db07d36dac1a7e3bb7bcc9af56bbe6158f9226a801", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "acc4ee0f373389734b9f0a86b268feb3dff98fb4c7faac4978bc960382ef8c1f", - "start_line": 240, - "name": "full_path", - "arity": 2 - }, - "put_top/2:289": { - "line": 289, - "guard": null, - "pattern": "module, value", - "kind": "defp", - "end_line": 291, - "ast_sha": "2db8dfe4dea8e4940271aeb73f92b1f44904828d2991be4f71ff2f09ea697675", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "00fb79fa05969cab4d964c0c2e8d7add2cc5019a32cc0fc508a9428294053927", - "start_line": 289, - "name": "put_top", - "arity": 2 - }, - "join_path/2:263": { - "line": 263, - "guard": null, - "pattern": "top, path", - "kind": "defp", - "end_line": 264, - "ast_sha": "f586374891a1a893e9e6f42f8be2c6d6815f53cae98f876996916ac38c8ba78c", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "df51d1136a1f25baf9d6c7119226f95115f94daeb68efc49110704a7b50502ad", - "start_line": 263, - "name": "join_path", - "arity": 2 - }, - "push/2:137": { - "line": 137, - "guard": "is_binary(path)", - "pattern": "module, path", - "kind": "def", - "end_line": 138, - "ast_sha": "17e9fd462203af661a09b4a87ba3272e8d63e86aa8fb8fef32020aed886ad2c1", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "f8f55625509b97974d4daf817720e40e2a73a89e9723403e5a28c8ed826fe4d8", - "start_line": 137, - "name": "push", - "arity": 2 - }, - "validate_path/1:107": { - "line": 107, - "guard": null, - "pattern": "path", - "kind": "def", - "end_line": 108, - "ast_sha": "451b0f2ca971ea0a11e75f9b6bf078340f32ead53b4929e4515c1592952fe60b", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "0649c59cbc02920f6b654532d920c092135f4797657293949c9635080f80bd8f", - "start_line": 107, - "name": "validate_path", - "arity": 1 - }, - "validate_forward!/2:93": { - "line": 93, - "guard": null, - "pattern": "_, plug", - "kind": "defp", - "end_line": 94, - "ast_sha": "32bbe56cbbf9d8d376766f2191b9c6b7fec3c39bd84c1cfeadeca577ca54d6c3", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "0b59f2f2606d5459ba8ecf2cbf612339adaa59f83a23ebad9c5cfdb4cf0c3ada", - "start_line": 93, - "name": "validate_forward!", - "arity": 2 - }, - "init/1:22": { - "line": 22, - "guard": null, - "pattern": "module", - "kind": "def", - "end_line": 25, - "ast_sha": "3f21752e9a90981459b3eef8f37fd207bd44ea78379aeaaa7bec39f2902aa15f", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "32b81ec0261e0c809e1043dedc1f7d427b4bef6587bd3751c20b06a925dbca80", - "start_line": 22, - "name": "init", - "arity": 1 - }, - "deprecated_trailing_slash/2:178": { - "line": 178, - "guard": null, - "pattern": "opts, top", - "kind": "defp", - "end_line": 190, - "ast_sha": "54605f27e04f9f66c9eb6149de5d34ca2c9c372e4ad8b4abc488579effe40b18", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "c03554b766737eed27994a1b42e299fc40dba54a479661e236440f2a7b661823", - "start_line": 178, - "name": "deprecated_trailing_slash", - "arity": 2 - }, - "join_as/2:274": { - "line": 274, - "guard": null, - "pattern": "_top, nil", - "kind": "defp", - "end_line": 274, - "ast_sha": "e2cc470835c15ca6003dcf0777f19c70d798b0da8c12a2d2560d44cf1f420ddf", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "40a3053ec120def3d64d2ac21b15ab1eda42804213c5e15531aa57cb633377d4", - "start_line": 274, - "name": "join_as", - "arity": 2 - }, - "join/7:251": { - "line": 251, - "guard": null, - "pattern": "top, path, alias, alias?, as, private, assigns", - "kind": "defp", - "end_line": 260, - "ast_sha": "9b1e57429d25e46c1cfd7636a6f9216d65400fae0145b49c7f5d932564170e44", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "9924f2210bed4618dd9945af736373df315d97a530b76ba9a94fb18a574c81b6", - "start_line": 251, - "name": "join", - "arity": 7 - }, - "__struct__/1:9": { - "line": 9, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 9, - "ast_sha": "5c01bfd9ec8e0c9fd7242c7bce0eee04b1e82fb225a09e7d266ba30ada11118b", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "acf16f4224198d313a058c19bec3cfc66d8da096fb4c14be3f74dc717d9ad6aa", - "start_line": 9, - "name": "__struct__", - "arity": 1 - }, - "validate_path/1:102": { - "line": 102, - "guard": "is_binary(path)", - "pattern": "path", - "kind": "def", - "end_line": 104, - "ast_sha": "78a5d4c8db73b770bc4f4e525160911eaa9b6fecb22e75ed00966af79a97f0a2", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "35e571e2e4e2e4e79d23edc17d95abcf2b98459f2fd32a15f748b43bcc0c5d58", - "start_line": 102, - "name": "validate_path", - "arity": 1 - }, - "__struct__/0:9": { - "line": 9, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 9, - "ast_sha": "c7d65aa1e58bf7143c55084b1b139e62e75f19ac4d6db446aada065829dfb1a5", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "acf16f4224198d313a058c19bec3cfc66d8da096fb4c14be3f74dc717d9ad6aa", - "start_line": 9, - "name": "__struct__", - "arity": 0 - }, - "route/8:31": { - "line": 31, - "guard": null, - "pattern": "line, module, kind, verb, path, plug, plug_opts, opts", - "kind": "def", - "end_line": 78, - "ast_sha": "780fc5ffcadecfaf3257b110a08edf3b59946c90090c20017e2a7f4ea026ccb7", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "af4ecb9231d083355a2a8b3017640c30c75e5bac6d7b5743e7a981ffe6f51392", - "start_line": 31, - "name": "route", - "arity": 8 - }, - "raise_invalid_host/1:207": { - "line": 207, - "guard": null, - "pattern": "host", - "kind": "defp", - "end_line": 209, - "ast_sha": "e44b24cefb784464d30d82e82e3d3152eb77a53b718162cf180c2913b2215ac2", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "ba42d3bc2aaa57fba69f0da787252eaf09af551ba28ed94c840f393593f6923d", - "start_line": 207, - "name": "raise_invalid_host", - "arity": 1 - }, - "push/2:141": { - "line": 141, - "guard": "is_list(opts)", - "pattern": "module, opts", - "kind": "def", - "end_line": 174, - "ast_sha": "940396795e82a4825b3b7d5932e2002b14d45696948c07a764b89129d8db6871", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "157ae5a1cc26a254429ee51a6105d3e5bc67287c0d872c8e8c747d345eb65f39", - "start_line": 141, - "name": "push", - "arity": 2 - }, - "validate_path/1:100": { - "line": 100, - "guard": null, - "pattern": "<<\"/\"::binary, _::binary>> = path", - "kind": "def", - "end_line": 100, - "ast_sha": "d32fb7ff229635de38d0fc2fcbe1399f389732426a9cc234347a1ffe9f9fa9b9", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "03223e63a1c79fea5bb1af00c4865987ea4408a5fbabbc43b749ee2a325d04ad", - "start_line": 100, - "name": "validate_path", - "arity": 1 - }, - "pipe_through/2:121": { - "line": 121, - "guard": null, - "pattern": "module, new_pipes", - "kind": "def", - "end_line": 131, - "ast_sha": "ea5ef91a0bdaf9f480aaa6f3df4fa162b518cf00bb84c30aa9ab07c4e08405cd", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "90f145ba87099a9fbee806babebaf550b83be56f9e386f84c17d69ca5f45a9cc", - "start_line": 121, - "name": "pipe_through", - "arity": 2 - }, - "append_unless_false/4:212": { - "line": 212, - "guard": null, - "pattern": "top, opts, key, fun", - "kind": "defp", - "end_line": 216, - "ast_sha": "685bf3680de4651fe2783a897822038d003456e860e411aa334afe3a46586e1d", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "1ef9681ddf27c3fb9e7b00fbde2e5dc5489f3a806eb5387ad62eca39ad2dd93d", - "start_line": 212, - "name": "append_unless_false", - "arity": 4 - }, - "validate_hosts!/1:195": { - "line": 195, - "guard": "is_binary(host)", - "pattern": "host", - "kind": "defp", - "end_line": 195, - "ast_sha": "64098d07779f680098ab87e0fa6de37fb77fbbea2480b85b1a7143a908e4fd8a", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "e5488b7e3ff85db8f90c634f3787ce47784629c5388b3e63a965714c810443ac", - "start_line": 195, - "name": "validate_hosts!", - "arity": 1 - }, - "update_pipes/2:285": { - "line": 285, - "guard": null, - "pattern": "module, fun", - "kind": "defp", - "end_line": 286, - "ast_sha": "ffa2ba412fb927d6606c7dc5a83bdb0bae6becb65c6a3d97f7437be23913d140", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "7566cadc2f48701be70ada3f898b7711a30f17abb686ffd27c9dc6c233860715", - "start_line": 285, - "name": "update_pipes", - "arity": 2 - }, - "validate_forward!/2:82": { - "line": 82, - "guard": "is_atom(plug)", - "pattern": "path, plug", - "kind": "defp", - "end_line": 89, - "ast_sha": "5df6cef865a39a7a1f359a9ac2f12b56b55a25c75992d84e89f8879500289a70", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "86b72de49ef6afd4a82d2b116c11c16ee48afa18281686e1ad60b7234713acf7", - "start_line": 82, - "name": "validate_forward!", - "arity": 2 - }, - "get_top/1:277": { - "line": 277, - "guard": null, - "pattern": "module", - "kind": "defp", - "end_line": 278, - "ast_sha": "09673d46960a03022645540eca59124b9e1f4886433331dc9f9ee8cc624ff87c", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "3688485e0d6a1590dad34dbc712ce953c81355e31964b3056f33f83ff524c549", - "start_line": 277, - "name": "get_top", - "arity": 1 - }, - "validate_hosts!/1:197": { - "line": 197, - "guard": "is_list(hosts)", - "pattern": "hosts", - "kind": "defp", - "end_line": 201, - "ast_sha": "e4e0b35e2e67ea00bec929df96c449423db829611e7b9312367afeeb9b132bb7", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "a3ad4b87b3fe8dec163927918305116ce452d87698b95b9d5835f3c0a51d55cb", - "start_line": 197, - "name": "validate_hosts!", - "arity": 1 - }, - "expand_alias/2:233": { - "line": 233, - "guard": null, - "pattern": "module, alias", - "kind": "def", - "end_line": 234, - "ast_sha": "179ce5ac5d96e3364056b1ba36ee07d442fb6a17aac40cb1168fa04e56b600b2", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "d9ab4ca8c3d3c3ad06c1f58e526511975603d05ee315b6bfe542c8979894810c", - "start_line": 233, - "name": "expand_alias", - "arity": 2 - }, - "join_alias/2:267": { - "line": 267, - "guard": "is_atom(alias)", - "pattern": "top, alias", - "kind": "defp", - "end_line": 270, - "ast_sha": "36762c9dbf5b2a40eac4abafc55b11cc60aea1eb1d2566402df6a219059b155d", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "dcf3c951de2c554bc2db76d098813917b600cccf00a620b3b72da0e2d071cbc5", - "start_line": 267, - "name": "join_alias", - "arity": 2 - }, - "update_stack/2:281": { - "line": 281, - "guard": null, - "pattern": "module, fun", - "kind": "defp", - "end_line": 282, - "ast_sha": "f40bc4d171854a25fc63988ad5b7d010b51e1ddaa8a7f1c5aed76cddaa37543f", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "67b664dc77121628cc772b1e8eac7c9a8c065e59a294b146831ad4eef507c3c0", - "start_line": 281, - "name": "update_stack", - "arity": 2 - }, - "get_attribute/2:294": { - "line": 294, - "guard": null, - "pattern": "module, attr", - "kind": "defp", - "end_line": 296, - "ast_sha": "9aa07cdd21291bbdfd174e120a91a1e49e948bf1ec43c104be6fdbc773d08eff", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "d360eeb3782cb9a85e83ddeb7df4187918bb5eeb510bd02107a9c02abbb6ebe8", - "start_line": 294, - "name": "get_attribute", - "arity": 2 - }, - "join_as/2:275": { - "line": 275, - "guard": "is_atom(as) or is_binary(as)", - "pattern": "top, as", - "kind": "defp", - "end_line": 275, - "ast_sha": "d369fc9a9671c77722913383992a17fa97b03003baa220206bd7adce940198ea", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "a96e42a2f6be3dabce512d61a05c3e27c71c717d624b721dc6a58b687164ab9c", - "start_line": 275, - "name": "join_as", - "arity": 2 - }, - "validate_hosts!/1:205": { - "line": 205, - "guard": null, - "pattern": "invalid", - "kind": "defp", - "end_line": 205, - "ast_sha": "aa4ba2f954444c36ebd10f4d836a5a95a5fae698a5839d558099776680c1c335", - "source_file": "lib/phoenix/router/scope.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/scope.ex", - "source_sha": "473d546c258ef0a798b62122f379490e96eecff86d1922d1b73b0de3fc8eb079", - "start_line": 205, - "name": "validate_hosts!", - "arity": 1 - } - }, - "Phoenix.Router.Route": { - "__struct__/0:28": { - "line": 28, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 28, - "ast_sha": "1617fb7eb06b3609f8e7b574946b49fcf9395ace039a75d4d9e861af7551ac41", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "5995dc95aeec0f228d6726cb38c22b689fb1422338cc6bd6f2aabfed4059c3d0", - "start_line": 28, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:28": { - "line": 28, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 28, - "ast_sha": "4f7bdbbd1a8932d21c43cbd62bb23b59a71d33e83aded47a829afaf2f4b9c169", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "5995dc95aeec0f228d6726cb38c22b689fb1422338cc6bd6f2aabfed4059c3d0", - "start_line": 28, - "name": "__struct__", - "arity": 1 - }, - "build/14:79": { - "line": 79, - "guard": "is_atom(verb) and is_list(hosts) and is_atom(plug) and (is_binary(helper) or helper == nil) and\n is_list(pipe_through) and is_map(private) and is_map(assigns) and is_map(metadata) and\n (=:=(kind, :match) or =:=(kind, :forward)) and is_boolean(trailing_slash?)", - "pattern": "line, kind, verb, path, hosts, plug, plug_opts, helper, pipe_through, private, assigns, metadata, trailing_slash?, warn_on_verify?", - "kind": "def", - "end_line": 114, - "ast_sha": "6c0dc4dc2075dd6f578027fc7927acd59d07ebeb482d60396348da8dce669294", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "8929cd7fe5b53191141dfade35ecb58c1366f08fd6324135ef6507f442314d3b", - "start_line": 79, - "name": "build", - "arity": 14 - }, - "build_dispatch/1:194": { - "line": 194, - "guard": null, - "pattern": "%Phoenix.Router.Route{kind: :match, plug: plug, plug_opts: plug_opts}", - "kind": "defp", - "end_line": 196, - "ast_sha": "04ad205a7abcdcfd6b31618c901b1585792863d911c8042a83d9a06cf00f7bab", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "0faf8012e1d9a810cc8d4fc4aa3ba9029c0c43f8f11a36a11527800c8473c6e9", - "start_line": 194, - "name": "build_dispatch", - "arity": 1 - }, - "build_dispatch/1:200": { - "line": 200, - "guard": null, - "pattern": "%Phoenix.Router.Route{kind: :forward, plug: plug, plug_opts: plug_opts, metadata: metadata}", - "kind": "defp", - "end_line": 209, - "ast_sha": "18c72a41139259b776c34d76f79990fb411eb00900ccf09ae61d76baf5ce2d43", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "645a7acef0483dc169fd15716254e86d1fb5e9180776c9ccfb1c9e6af016f0fb", - "start_line": 200, - "name": "build_dispatch", - "arity": 1 - }, - "build_host_match/1:135": { - "line": 135, - "guard": null, - "pattern": "[]", - "kind": "def", - "end_line": 135, - "ast_sha": "828146fbc543280a3d1eeb068ed69b99f975799e0e6d6a08c14c20e57fc54629", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "1f5d48c7a5864439542dede555b77c782cec79a075ea0e0eb1df1721bf7ab800", - "start_line": 135, - "name": "build_host_match", - "arity": 1 - }, - "build_host_match/1:137": { - "line": 137, - "guard": null, - "pattern": "[_ | _] = hosts", - "kind": "def", - "end_line": 138, - "ast_sha": "b202ec3e70e9206bd51280a10837704f790fdf32cafbdbb07312257686d2455f", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "a710acc3af3a27530602ba447d5c5045411975e985bd169fddfdfabe4aa4f362", - "start_line": 137, - "name": "build_host_match", - "arity": 1 - }, - "build_params/0:214": { - "line": 214, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 223, - "ast_sha": "a809642cdda0f3a91ed65a46c37d37fb41a7f3dd3e26db004425c1b981a7c413", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "e1d9e5b227551cb4f23bc1295ff991bdcde2bf32860fb85617ea0f0130167bd1", - "start_line": 214, - "name": "build_params", - "arity": 0 - }, - "build_path_and_binding/1:146": { - "line": 146, - "guard": null, - "pattern": "%Phoenix.Router.Route{path: path} = route", - "kind": "defp", - "end_line": 153, - "ast_sha": "561d3ef406e023606c89aa03e90988c6e167d4e61e440bd7886d32959e3bea79", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "3856da158ccb0e4270c58832681e9bd0905a42093d8d5e465350def907673b30", - "start_line": 146, - "name": "build_path_and_binding", - "arity": 1 - }, - "build_path_params/1:144": { - "line": 144, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 144, - "ast_sha": "28db94cabd97180b73363b1ae2df99af033543710e5a96fe3d1f70b4f7fa2ff4", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "d4fb02a720e15aa51746253a8df649ac82f572f34d969a0b48b8e2a966e0561c", - "start_line": 144, - "name": "build_path_params", - "arity": 1 - }, - "build_prepare/1:172": { - "line": 172, - "guard": null, - "pattern": "route", - "kind": "defp", - "end_line": 182, - "ast_sha": "6c2ba511926ceb7fb5286e86a09629387520a1f0911bdd696492ff330aadcce7", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "6517ea6745d74104848ca6964ce6a1e5de05dbcd50df5461285d4f9a4e1ed5e5", - "start_line": 172, - "name": "build_prepare", - "arity": 1 - }, - "build_prepare_expr/2:186": { - "line": 186, - "guard": "data == %{}", - "pattern": "_key, data", - "kind": "defp", - "end_line": 186, - "ast_sha": "93e00ce13702c0e1d893237dcf6cca580a0946e89e62a3ce593b27d9763d7558", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "2210f7e47d37e530d094feebf993d17ddfcc281d4631cfca83af9d93cdafdf32", - "start_line": 186, - "name": "build_prepare_expr", - "arity": 2 - }, - "build_prepare_expr/2:188": { - "line": 188, - "guard": null, - "pattern": "key, data", - "kind": "defp", - "end_line": 191, - "ast_sha": "8e3eaa072b90a17d0ddb60dd38a6a078244b8ddff49efa8697f3986e8e90972c", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "3c86ae9bad5b07cf81ef703e53e11591fd509e8d9b519b05f14b74478a5d0dfa", - "start_line": 188, - "name": "build_prepare_expr", - "arity": 2 - }, - "call/2:51": { - "line": 51, - "guard": null, - "pattern": "%{path_info: path, script_name: script} = conn, {fwd_segments, plug, opts}", - "kind": "def", - "end_line": 56, - "ast_sha": "f4849fc0d1e48803e9e9d5b4353fd309f7c9829f65a601215e2ee73e3652fa6f", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "f7f1235ecf41754c131e16caedbfaa610af0e8afbbb15eec02cb1b298fb8628b", - "start_line": 51, - "name": "call", - "arity": 2 - }, - "exprs/1:121": { - "line": 121, - "guard": null, - "pattern": "route", - "kind": "def", - "end_line": 131, - "ast_sha": "102aee2d246ae1e65d4117d69fad99724e25a20df75207e6bc57c1e836911a58", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "4c3170bfba67e2b1d5b2f86f10c946b0b946872a9c87800902e380cd765e846f", - "start_line": 121, - "name": "exprs", - "arity": 1 - }, - "init/1:48": { - "line": 48, - "guard": null, - "pattern": "opts", - "kind": "def", - "end_line": 48, - "ast_sha": "c0bc7209df8554b2766ba259e7d47f64a720d830d71a2d4b624c1623e319c32b", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "1bcc2482db33f4e2e398621a48e6485065cdf19c0ceb245b42381a1a0699ec49", - "start_line": 48, - "name": "init", - "arity": 1 - }, - "merge_params/2:230": { - "line": 230, - "guard": null, - "pattern": "%Plug.Conn.Unfetched{}, path_params", - "kind": "def", - "end_line": 230, - "ast_sha": "11fb868a8ebb3179e0a296dff8315db936294a61478f3f8009076d9c76153dc6", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "77ead829f49a6f6303ceb853903d6582bdb3d18dcfe35fe1e2ff1353fec079e5", - "start_line": 230, - "name": "merge_params", - "arity": 2 - }, - "merge_params/2:231": { - "line": 231, - "guard": null, - "pattern": "params, path_params", - "kind": "def", - "end_line": 231, - "ast_sha": "6556a9d5f9c92a99bd5308e4a9794978563beadbc99690ef1eb6c688d985fe12", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "eb51d87be5431d8cd406b8820c4cd978398aa07f4a3ed509ee6dd478ad55f329", - "start_line": 231, - "name": "merge_params", - "arity": 2 - }, - "rewrite_segments/1:157": { - "line": 157, - "guard": null, - "pattern": "segments", - "kind": "defp", - "end_line": 169, - "ast_sha": "e8a90ed4cb58f2ad1e85f83ad05f9af8786b20083a4e36ba30a7525223fce09d", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "369c260d4d8f849e9d14cbe9fad7d397e8f2d550bc778fae455be4441cd4f145", - "start_line": 157, - "name": "rewrite_segments", - "arity": 1 - }, - "verb_match/1:141": { - "line": 141, - "guard": null, - "pattern": ":*", - "kind": "defp", - "end_line": 141, - "ast_sha": "4fe21c9b344c2b8374001eef8fa51ae5ee88437a47e7d7e9fb691df49db22d56", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "2a3fda9568a9e79c8ca9e7073454ac8db27b91f7d6e566c87a4ab7f65b1ab2a6", - "start_line": 141, - "name": "verb_match", - "arity": 1 - }, - "verb_match/1:142": { - "line": 142, - "guard": null, - "pattern": "verb", - "kind": "defp", - "end_line": 142, - "ast_sha": "d063e01b6975750cda82c403ea799358ea2dc469df1dce62aea7d0ff30867c22", - "source_file": "lib/phoenix/router/route.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/route.ex", - "source_sha": "6d96631db8f69c1109ac9e0d9dee51d57b2043d13775eafa6311cd1a3b024801", - "start_line": 142, - "name": "verb_match", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Auth": { - "datetime_now/1:1126": { - "line": 1126, - "guard": null, - "pattern": "%{timestamp_type: :naive_datetime}", - "kind": "defp", - "end_line": 1126, - "ast_sha": "ab7cef9e0b77edfc0287b98b471c814a2b1d411dec87878408839449497e9c43", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "5a5ff452e447ae0caf11367406061a4ebbd8c238ba46b9e1e83e9f6ae73f57ac", - "start_line": 1126, - "name": "datetime_now", - "arity": 1 - }, - "build_hashing_library!/1:312": { - "line": 312, - "guard": null, - "pattern": "opts", - "kind": "defp", - "end_line": 322, - "ast_sha": "2852cdcd226c514579055a7afcee9c89b3df5b2ef7f304e9e622d52ad38fffb0", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "25a225ec94f083432c8cece7b3041e03f5d5b63a2a231ad028a223e6518b9d90", - "start_line": 312, - "name": "build_hashing_library!", - "arity": 1 - }, - "run/2:174": { - "line": 174, - "guard": null, - "pattern": "args, test_opts", - "kind": "def", - "end_line": 251, - "ast_sha": "29e22ca550f9c4034d99d34c1a41b3e7683e819fbda3b5bbc1279f6ea505efb8", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "0051de608d832b8ffac2fc25e32bac7f21491247fc47d4ead6c9d6c4ab4bd175", - "start_line": 174, - "name": "run", - "arity": 2 - }, - "datetime_module/1:1123": { - "line": 1123, - "guard": null, - "pattern": "%{timestamp_type: :utc_datetime}", - "kind": "defp", - "end_line": 1123, - "ast_sha": "4a9dc74f18102c0cbe096400d66368e8ba1c8af62a3a59f1177cf108c9db96f0", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "ffaaaae2cd31e81101fe2c5fcb4b06ee26e7f2a90bec2d84454c91e38d37ca85", - "start_line": 1123, - "name": "datetime_module", - "arity": 1 - }, - "is_new_scope?/2:388": { - "line": 388, - "guard": null, - "pattern": "existing_scopes, bin_key", - "kind": "defp", - "end_line": 390, - "ast_sha": "cbe004c6bebca1787df8f88d4dfd3c318494a6ad968df77a5fe89ae9980d7624", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "5ca7f52fd09800e18736111685844ffb551dce6559177c33b20d3de994a9e61c", - "start_line": 388, - "name": "is_new_scope?", - "arity": 2 - }, - "router_scope/1:978": { - "line": 978, - "guard": null, - "pattern": "%Mix.Phoenix.Context{schema: schema} = context", - "kind": "defp", - "end_line": 984, - "ast_sha": "0d7fc0f2892e49997f1fd01ca54d2985de72520b87ad0a418762d749629cf57d", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "a10df912d236367b4ddac873fa63ed0935e8d382fc74d7f2263ec8b9f5f2018f", - "start_line": 978, - "name": "router_scope", - "arity": 1 - }, - "files_to_be_generated/1:478": { - "line": 478, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 601, - "ast_sha": "e5cac31341e58c35ce003e8b2a5aa04202c05741302e5844b6eb8f3eb1ada548", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "03e73ca95a75c1d2d78a9dde121b185af44f5852510091c17182762b6ed61c7a", - "start_line": 478, - "name": "files_to_be_generated", - "arity": 1 - }, - "maybe_inject_mix_dependency/2:671": { - "line": 671, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{mix_dependency: mix_dependency}", - "kind": "defp", - "end_line": 700, - "ast_sha": "bfea69ed6589347c31e537aa1cf1745263af39081038e1a43cde142d104d1949", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "216e4234777545924a22b369d849911dbb126111cc3c71c4af982fcdd36f8141", - "start_line": 671, - "name": "maybe_inject_mix_dependency", - "arity": 2 - }, - "inject_hashing_config/2:835": { - "line": 835, - "guard": null, - "pattern": "context, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", - "kind": "defp", - "end_line": 867, - "ast_sha": "d9dbbf759fd5e43c3d7bb06835606442e7fa0df292aa12f683a022547ea278dc", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "2ee79ffe5aec84d00c6d26463294e02456780f33e6ae25e5269acc318919a04a", - "start_line": 835, - "name": "inject_hashing_config", - "arity": 2 - }, - "inject_routes/3:660": { - "line": 660, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, paths, binding", - "kind": "defp", - "end_line": 668, - "ast_sha": "4172784d0a8152f0c66958a6be6272f80e4e64e3da9826af11f18facfa7a394e", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "59d6b1bccf03c14de79ea784700fe1481ea2e4a747aa0d3cf731930c55be0c20", - "start_line": 660, - "name": "inject_routes", - "arity": 3 - }, - "test_case_options/1:1120": { - "line": 1120, - "guard": "is_atom(adapter)", - "pattern": "adapter", - "kind": "defp", - "end_line": 1120, - "ast_sha": "41e6719b4a2e227d457699d30090fa21d3c461404f9dc5cb0aa07de529d33d9b", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "d3fee16e797b3237563e464208164395dd26fa533225d5f33d3ac14073cfff67", - "start_line": 1120, - "name": "test_case_options", - "arity": 1 - }, - "inject_tests/3:628": { - "line": 628, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_file: test_file} = context, paths, binding", - "kind": "defp", - "end_line": 634, - "ast_sha": "32e1f0382bc89da5278950bbf731f9875eaabc35a3adf641a137e3a4806459da", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "6244102b2a8bf4aa2d86359c207b39406fed78aeb29be6173c03b1efb20a0076", - "start_line": 628, - "name": "inject_tests", - "arity": 3 - }, - "potential_layout_file_paths/1:827": { - "line": 827, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app}", - "kind": "defp", - "end_line": 831, - "ast_sha": "3c97c56b7a2645d2ac47ff7bb4bbcc73c6273c6a26591cacae9643571b97a4b0", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "6211b1f16a40c9628dc37fccb095093382ad58b96fe5b456fe8c29f5463cad71", - "start_line": 827, - "name": "potential_layout_file_paths", - "arity": 1 - }, - "raise_with_help/2:1089": { - "line": 1089, - "guard": null, - "pattern": "msg, :phx_generator_args", - "kind": "defp", - "end_line": 1091, - "ast_sha": "3020f6663792f64596cb9e1200a7276e8137994d20debe38addfc4dd789b3e23", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "9e68a0edc6684ad1f4504ccda38c68e82088944bb6be35ba9d10320c4db46c8d", - "start_line": 1089, - "name": "raise_with_help", - "arity": 2 - }, - "raise_with_help/2:1071": { - "line": 1071, - "guard": null, - "pattern": "msg, :general", - "kind": "defp", - "end_line": 1073, - "ast_sha": "cfbdbb965ba9e03b4489a2c7d52ec8a12048092fc12a95e6b824312b667c2a23", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "40dd554515ab7afa31e52625a35cce2370ead4347d80317a9665dae485639159", - "start_line": 1071, - "name": "raise_with_help", - "arity": 2 - }, - "maybe_inject_router_plug/2:750": { - "line": 750, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, binding", - "kind": "defp", - "end_line": 774, - "ast_sha": "a383ac647e02984cebff116525fa181219b9fc210be6e62bd10ffd42b47b4daa", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "1d7bf2aa758287aeee01b48ce0428279bd54fc8f42d63159dd076d5fbd2adf12", - "start_line": 750, - "name": "maybe_inject_router_plug", - "arity": 2 - }, - "maybe_inject_app_layout_menu/2:777": { - "line": 777, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding", - "kind": "defp", - "end_line": 818, - "ast_sha": "f3fcafa095bc56434f30b1e5a311e917922b771d724ae5c13bc7a14c42072441", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "cd93f22536f74ad959532a9822148f29fb84bf6072173bbdbd161867b60ef1ed", - "start_line": 777, - "name": "maybe_inject_app_layout_menu", - "arity": 2 - }, - "prompt_for_conflicts/1:428": { - "line": 428, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 433, - "ast_sha": "abeb352e91a7373299c3249c922a1fdb7ac8850e9cb3b44e0af90c2cd909acd9", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "231db0cdfeca98e4545e95eb50f349d470cf8ff282c4e1e43beb676a9c1be12b", - "start_line": 428, - "name": "prompt_for_conflicts", - "arity": 1 - }, - "test_case_options/1:1119": { - "line": 1119, - "guard": null, - "pattern": "Ecto.Adapters.Postgres", - "kind": "defp", - "end_line": 1119, - "ast_sha": "9182bc7d94fcba01e7385cd2ba2dbe426e0369b68efff2119f2aece41aa7526d", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "83e58942ef65c5baf9733d297f55ee811af0589ad32636f0bcd41ef91e772e88", - "start_line": 1119, - "name": "test_case_options", - "arity": 1 - }, - "inject_before_final_end/2:991": { - "line": 991, - "guard": null, - "pattern": "content_to_inject, file_path", - "kind": "defp", - "end_line": 1010, - "ast_sha": "4ebf59e80a43be391fcb6118c21f44174b4650772cc13280b2265474c4b9b737", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "b77de970d65b3fca8d0397a81f22a9f345fa662dccde7b6ed01a1a9c2cf0b8ef", - "start_line": 991, - "name": "inject_before_final_end", - "arity": 2 - }, - "print_injecting/2:1050": { - "line": 1050, - "guard": null, - "pattern": "file_path, suffix", - "kind": "defp", - "end_line": 1051, - "ast_sha": "6ef8e834a0d424143b6a345c4a33a6d761d2255ad8d7404de1d90b008302b2e5", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "e47e84d044af0ddc2d4070524c1ba32f4923889e065fe71ec3ebb496cfc2a7bb", - "start_line": 1050, - "name": "print_injecting", - "arity": 2 - }, - "raise_with_help/2:1104": { - "line": 1104, - "guard": null, - "pattern": "msg, :hashing_lib", - "kind": "defp", - "end_line": 1106, - "ast_sha": "98f4b197d84d3f74712d72031672e1d7329b40f3333ae0daa3ad1ea736e0ce50", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "8f2456b46b9890ca5fa59a37fabf7ac26eeca6cb288bf4a5093d8a66c422b621", - "start_line": 1104, - "name": "raise_with_help", - "arity": 2 - }, - "print_unable_to_read_file_error/2:1054": { - "line": 1054, - "guard": null, - "pattern": "file_path, help_text", - "kind": "defp", - "end_line": 1062, - "ast_sha": "a67071b500e520fb1f1bde0428e8ce696b55c210239a6450311b37947914ccca", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "329ae345b236f8b2a3acd6da08e108a67e01210c1b4d2557fdd9e123a5c7d914", - "start_line": 1054, - "name": "print_unable_to_read_file_error", - "arity": 2 - }, - "inject_context_functions/3:619": { - "line": 619, - "guard": null, - "pattern": "%Mix.Phoenix.Context{file: file} = context, paths, binding", - "kind": "defp", - "end_line": 625, - "ast_sha": "b820a725926f8ee740d0e816dafcff0dce6f8bc8ea9ce8d26788951c5a727529", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "3cfebdb6c536f3a28329f1645de10c04196323e78772d02e5f59f93f9e398475", - "start_line": 619, - "name": "inject_context_functions", - "arity": 3 - }, - "inject_scope_config/2:878": { - "line": 878, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding", - "kind": "defp", - "end_line": 911, - "ast_sha": "bc73bb670d2525a853155ca3d2b6a4372678d739015a0f83f414f34218b7767b", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "867494258afb20b0cd54f38e905807a0c3ac03308e5eba292a7c78a40c9a8c55", - "start_line": 878, - "name": "inject_scope_config", - "arity": 2 - }, - "print_shell_instructions/1:959": { - "line": 959, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 975, - "ast_sha": "2b17d2bf44a28b898052091d4c3b4e71f33471771725592ee0215fcbec1b90f3", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "7d1cf9e89dd6705e388e0f4ba2b63aaaa8fdb0310c87905f3ac4bcb833c200dd", - "start_line": 959, - "name": "print_shell_instructions", - "arity": 1 - }, - "maybe_inject_agents_md/3:914": { - "line": 914, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", - "kind": "defp", - "end_line": 956, - "ast_sha": "1db7b4d3fb34d453c2f86c87614b0882291c0a84f2b85365d7d06d66744fc74a", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "ab9915796ba1f6f68db74b2047c0d3da6a1a2d680fa838eaeea50f874f548b65", - "start_line": 914, - "name": "maybe_inject_agents_md", - "arity": 3 - }, - "default_hashing_library_option/0:328": { - "line": 328, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 331, - "ast_sha": "9179d2cfd8f33396b31efe78a75348215a3f87a8b14ce9af2f1b5a2d31070721", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "96407b6ed9df080fea251747edc6cf6ffb9d6741aaf47c7e9d0dd15007a86083", - "start_line": 328, - "name": "default_hashing_library_option", - "arity": 0 - }, - "datetime_module/1:1122": { - "line": 1122, - "guard": null, - "pattern": "%{timestamp_type: :naive_datetime}", - "kind": "defp", - "end_line": 1122, - "ast_sha": "69919f24a5d79b372b16a60da3a7ca3660453025025845dcee2ba8162b3c5aeb", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "da6eb9a92cc83e90f740d8d6ae31269ccfb60ee556d3edcecf18b010980c4295", - "start_line": 1122, - "name": "datetime_module", - "arity": 1 - }, - "maybe_inject_router_import/2:703": { - "line": 703, - "guard": null, - "pattern": "%Mix.Phoenix.Context{context_app: ctx_app} = context, binding", - "kind": "defp", - "end_line": 747, - "ast_sha": "2aa53abc3715dafe14a7a0ca60b39eee33bdbe22571e4ac1289690265ff5cfc8", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "301653b3f8878ac96a5cf9c4a6208119ef26e9dbd5e4e90f203dceed64803d85", - "start_line": 703, - "name": "maybe_inject_router_import", - "arity": 2 - }, - "inject_conn_case_helpers/3:650": { - "line": 650, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, paths, binding", - "kind": "defp", - "end_line": 657, - "ast_sha": "60a28f45743b05de6205b819020a453d414f51ae6e48ac7949849912b10fd661", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "aff6f7d4e233ba52b419c5a05ee7c124a949048929e1cb288f8dcfc950e4475c", - "start_line": 650, - "name": "inject_conn_case_helpers", - "arity": 3 - }, - "indent_spaces/2:1023": { - "line": 1023, - "guard": "is_binary(string) and is_integer(number_of_spaces)", - "pattern": "string, number_of_spaces", - "kind": "defp", - "end_line": 1029, - "ast_sha": "02b7e38afc642d2d491e80f9bc138020675600be4b4ee4992ab5fadeca03302c", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "e3718ff2396ab598a8e2e98d97c795101b6fcdeb357215e36eaaa4ad325dc831", - "start_line": 1023, - "name": "indent_spaces", - "arity": 2 - }, - "get_ecto_adapter!/1:1042": { - "line": 1042, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{repo: repo}", - "kind": "defp", - "end_line": 1046, - "ast_sha": "2857a865ef8b4f280163322e42db8c6bf93c59041f1d894268a5f027eb67afc6", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "7f02aa09415f3c4fb7b7584b8f9fbe1fdb595f9f389ad651c25b1aac62dbea87", - "start_line": 1042, - "name": "get_ecto_adapter!", - "arity": 1 - }, - "remap_files/1:605": { - "line": 605, - "guard": null, - "pattern": "files", - "kind": "defp", - "end_line": 606, - "ast_sha": "81e51bed68573fc09124ff69574449840d4095b398248d290cd0e28c42b2c665", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "d878e2c7ca4e95eba1223934545b2317e192841a186d236ca4e2d9439b3d3a39", - "start_line": 605, - "name": "remap_files", - "arity": 1 - }, - "generated_with_no_html?/0:293": { - "line": 293, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 301, - "ast_sha": "dea71c64fb54f9a0fe3e54697d9239c858fd68014c131817e072f4b244137209", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "5410d34b26908bd3a7709eac6dfe9b14b758cff498afc127059e27307bf285dd", - "start_line": 293, - "name": "generated_with_no_html?", - "arity": 0 - }, - "find_scope_name/2:360": { - "line": 360, - "guard": null, - "pattern": "context, existing_scopes", - "kind": "defp", - "end_line": 381, - "ast_sha": "bf5a3a39c03cb858a66d503bd1c5675c7e1480524f425c08b9600f148bcb8f76", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "e2769268ec41e9aba442a23db17136d54913e07353e06bb8d67d2e4ddd162a2e", - "start_line": 360, - "name": "find_scope_name", - "arity": 2 - }, - "web_path_prefix/1:988": { - "line": 988, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{web_path: nil}", - "kind": "defp", - "end_line": 988, - "ast_sha": "53ee3b94f81e0c1c9ea061599990930781627c1f3358667fcb64a633935b91d5", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "1e0d12dbfe606281f4d52aa45bf2eb7368de839cb4e09f9847dc43ef1b9df082", - "start_line": 988, - "name": "web_path_prefix", - "arity": 1 - }, - "datetime_now/1:1127": { - "line": 1127, - "guard": null, - "pattern": "%{timestamp_type: :utc_datetime}", - "kind": "defp", - "end_line": 1127, - "ast_sha": "ae9ee4fe31d93bfb5dd08a916c741ff26794417c98bf51195ddbbdef579403d2", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "7f46cfd7cc88a33763da4e7be3c02f1c18cbba85380b8983273c5b67d0bba06e", - "start_line": 1127, - "name": "datetime_now", - "arity": 1 - }, - "validate_required_dependencies!/0:266": { - "line": 266, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 289, - "ast_sha": "215f56979e5a9ffab5c5c717a6d9cfbc43c4edd21cc077536f55a58c5a0b93ef", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "d48c001a2f36a8da613fa20c108f4bd48b1bdd7a3b6941c1bdad39d7914f9f8c", - "start_line": 266, - "name": "validate_required_dependencies!", - "arity": 0 - }, - "print_injecting/1:1050": { - "line": 1050, - "guard": null, - "pattern": "x0", - "kind": "defp", - "end_line": 1050, - "ast_sha": "7b0a4446c2774727086335406acb0fba0e1ba5c9d97a32873b2b24d247817cbf", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "dd97eb4958e314405d344211a6db8df431e131d1890749f7da1c181fac1b474e", - "start_line": 1050, - "name": "print_injecting", - "arity": 1 - }, - "timestamp/0:1032": { - "line": 1032, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 1034, - "ast_sha": "f92225114515dfbf6f7bce4421d1ddd729c9aa3dabf028f410289210173cecdc", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "31815f67847bad4ae7aa82b79514b445b4ddd807b20356094669e72b46c33894", - "start_line": 1032, - "name": "timestamp", - "arity": 0 - }, - "copy_new_files/3:609": { - "line": 609, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding, paths", - "kind": "defp", - "end_line": 616, - "ast_sha": "fef5eb821ac1123c94bea2dc3a6db75b83131f50f805d1a3b90167b9bfc07621", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "e437877a206c52be2f064577f0b72865be75b6dc5258890e20a3863cfaf98385", - "start_line": 609, - "name": "copy_new_files", - "arity": 3 - }, - "run/1:174": { - "line": 174, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 174, - "ast_sha": "45d461968b8215bef2c6c061de66aed0ee82599bff15275e08028708db757d74", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "0525c212f181234f23d15f84712dae67cb2762f3bbb869470817c1a47a2a7962", - "start_line": 174, - "name": "run", - "arity": 1 - }, - "validate_args!/1:260": { - "line": 260, - "guard": null, - "pattern": "[_, _, _]", - "kind": "defp", - "end_line": 260, - "ast_sha": "1b56028c8938756c69633abc964cb1721b9b1668ddab2bfb2b50e8d0124b618e", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "16cf7b016db0f7cb3a20512823319f180dd1125b6c2c3d225c3dc0b1df1aed5c", - "start_line": 260, - "name": "validate_args!", - "arity": 1 - }, - "scope_config_string/4:411": { - "line": 411, - "guard": null, - "pattern": "context, key, default_scope, assign_key", - "kind": "defp", - "end_line": 423, - "ast_sha": "a77d656b01efb542247dfd9c7677841c829ea079c7c3eae0dc146bd4091e3b77", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "03f6cce830305196bdad40f6f452829dc7a4a702583620b19245738d64f2cac8", - "start_line": 411, - "name": "scope_config_string", - "arity": 4 - }, - "raise_with_help/1:1067": { - "line": 1067, - "guard": null, - "pattern": "msg", - "kind": "def", - "end_line": 1068, - "ast_sha": "b7cb2cf757347e02bac3da8bcbaee59b7b5e47d3bf8b31f68f28635bbff8b05f", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "5df5fd4354d460660b5e407826d2aa160af611f6f1175fb83fc96dffe9752c92", - "start_line": 1067, - "name": "raise_with_help", - "arity": 1 - }, - "put_live_option/1:1130": { - "line": 1130, - "guard": null, - "pattern": "schema", - "kind": "defp", - "end_line": 1150, - "ast_sha": "964b87401223e20ff5296b529c2e9bc6c019a54a9a0335b4bb2a9b4ff54ca9c9", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "69b3ba4a4111735f31a866af2915599769ffb64128ae006c537386bd238a60c4", - "start_line": 1130, - "name": "put_live_option", - "arity": 1 - }, - "datetime_module/1:1124": { - "line": 1124, - "guard": null, - "pattern": "%{timestamp_type: :utc_datetime_usec}", - "kind": "defp", - "end_line": 1124, - "ast_sha": "8e48feb00ef9d4da225d971648ecc0a8045a775871453849ebb7c5e9e3ccbf29", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "85bac05f0db2a217306fec2025b365dcb7977a5f4daf96a5e41f23752c9b7e88", - "start_line": 1124, - "name": "datetime_module", - "arity": 1 - }, - "datetime_now/1:1128": { - "line": 1128, - "guard": null, - "pattern": "%{timestamp_type: :utc_datetime_usec}", - "kind": "defp", - "end_line": 1128, - "ast_sha": "1a6d987cfea779ad40f2314b099d738ec8917d26b4f9f5f1bf469981d903c44c", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "108fa5ce6e67c83c841e9047c9922ae8a7d69e1ddb3b61161344d148b022258b", - "start_line": 1128, - "name": "datetime_now", - "arity": 1 - }, - "scope_config/3:335": { - "line": 335, - "guard": null, - "pattern": "context, requested_scope, assign_key", - "kind": "defp", - "end_line": 356, - "ast_sha": "04ce396601924f3d70dd7574fa8e1f48726218ccab12bf5ccd1818f6abeb8a3b", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "1e0122f932d2d0977393e4d5fcdc5efd5b6ff04fdc47113eca184e2bc37c6e0a", - "start_line": 335, - "name": "scope_config", - "arity": 3 - }, - "pad/1:1038": { - "line": 1038, - "guard": null, - "pattern": "i", - "kind": "defp", - "end_line": 1038, - "ast_sha": "a890a4d06d1c2099f5b0318876448a5612eaa099140679eb7ee14d2add5a7efa", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "019ee63a3ac952acdb672c9b9c381889dbecd8c4fea6d62ffa991c27316520a9", - "start_line": 1038, - "name": "pad", - "arity": 1 - }, - "get_layout_html_path/1:821": { - "line": 821, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 824, - "ast_sha": "699288801460547cf7bfcd7e146085c068f72cd3df946290ed62c4f96d581ccf", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "084a4e7de863bb6576596291902f4eacb1116e29c6c8bb021120f799f394e5d8", - "start_line": 821, - "name": "get_layout_html_path", - "arity": 1 - }, - "inject_context_test_fixtures/3:637": { - "line": 637, - "guard": null, - "pattern": "%Mix.Phoenix.Context{test_fixtures_file: test_fixtures_file} = context, paths, binding", - "kind": "defp", - "end_line": 647, - "ast_sha": "a56e9e6ed037b0ee3dc1d5d9fbcdc5e57dc4419e98b3f2c536c01ce42d2acbf3", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "72cde1ba57ef19b050af925ce5e5359bc3f35e9e2ee9df6554cdafd5fe501124", - "start_line": 637, - "name": "inject_context_test_fixtures", - "arity": 3 - }, - "prepend_newline/1:1040": { - "line": 1040, - "guard": "is_binary(string)", - "pattern": "string", - "kind": "defp", - "end_line": 1040, - "ast_sha": "694fcb60156c336cf8427ad250a356258b28e6212824dbdd46e55eacc1e1f44c", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "300ca99d53e6ffcf82085a37b235ffe2e4936386b623570bc8ca98c63ee606f9", - "start_line": 1040, - "name": "prepend_newline", - "arity": 1 - }, - "pad/1:1037": { - "line": 1037, - "guard": "i < 10", - "pattern": "i", - "kind": "defp", - "end_line": 1037, - "ast_sha": "5a8f6dba31e95ec6c137ce19a28fffb418b45cad50e7c7fe604c8a8406570326", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "b702f9d2b2eb412b80351a1db02d6367b03d9b917466520286d2f44bf08ef1dd", - "start_line": 1037, - "name": "pad", - "arity": 1 - }, - "new_scope/4:393": { - "line": 393, - "guard": null, - "pattern": "context, key, default_scope, assign_key", - "kind": "defp", - "end_line": 407, - "ast_sha": "c9ac8157a5914fef3b068b6100a2a975fff89f952ee34b7c5a1095fed0d2a454", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "bad773ef6ac7d5bc1b6588aefde26f8c272b3fac41cb4df4f912b7a442512b2b", - "start_line": 393, - "name": "new_scope", - "arity": 4 - }, - "web_path_prefix/1:989": { - "line": 989, - "guard": null, - "pattern": "%Mix.Phoenix.Schema{web_path: web_path}", - "kind": "defp", - "end_line": 989, - "ast_sha": "1a94b3321aaabc91c2d556d5b6d9943d9b0a24f2e2f64631f8e16a2e27140d59", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "5fd8ceef028de56bb6ab1c6e3b351fb8997177dd17886d0447c27f69b18c264b", - "start_line": 989, - "name": "web_path_prefix", - "arity": 1 - }, - "read_file/1:1016": { - "line": 1016, - "guard": null, - "pattern": "file_path", - "kind": "defp", - "end_line": 1019, - "ast_sha": "c82bd16318e344469d128f78331f2017591309c3843aea39f800e2c77551fd04", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "4e7401c080ff7dc56ec5fa35f7104985a5dac23d5f9c94868d676bc425bcffe3", - "start_line": 1016, - "name": "read_file", - "arity": 1 - }, - "web_app_name/1:254": { - "line": 254, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context", - "kind": "defp", - "end_line": 257, - "ast_sha": "c574b61ac11515305e348595f28331fd50b0b31d51844c73535a34bc56fd75fd", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "f130a0cf8a9e7d2e5042e77a57baf52119b0d59e9cd5c0930198927e66035295", - "start_line": 254, - "name": "web_app_name", - "arity": 1 - }, - "generated_with_no_assets_or_esbuild?/0:304": { - "line": 304, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 308, - "ast_sha": "07a0a731777f36cd53a4271a975f350e3a384bf99758c9483c56e971650334db", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "780e6109acef81d9c14dc39b7b339c52a19537074ce852a91e4cc1b73cf6c779", - "start_line": 304, - "name": "generated_with_no_assets_or_esbuild?", - "arity": 0 - }, - "validate_args!/1:262": { - "line": 262, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 263, - "ast_sha": "ea8e3213d2e54dd0152e93e9d31ecdc162de6b86b60c8a0edae5839f7ef68933", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "7a5cf251f3634c1231a3092f9e00d3b923d1f5fc99e2b03a24dd8feea51d298f", - "start_line": 262, - "name": "validate_args!", - "arity": 1 - }, - "maybe_inject_scope_config/2:870": { - "line": 870, - "guard": null, - "pattern": "%Mix.Phoenix.Context{} = context, binding", - "kind": "defp", - "end_line": 874, - "ast_sha": "f44d4b55f20ba1270fbef6c053601c03d4a9288beeabfcd3645edbc6710719e5", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "e2cd069889d02d01ef4f8178f99a3526688fc1420f836997d731391af0d7b0f4", - "start_line": 870, - "name": "maybe_inject_scope_config", - "arity": 2 - }, - "prompt_for_scope_conflicts/1:436": { - "line": 436, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 473, - "ast_sha": "71087d7ec6d66698f2c609354e098bdbc1c33b67679050421e53a46920b11395", - "source_file": "lib/mix/tasks/phx.gen.auth.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth.ex", - "source_sha": "bd3636aac24ab6435493098e9d35191198d2d42f0c051f36623a851a166b4327", - "start_line": 436, - "name": "prompt_for_scope_conflicts", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Auth.Injector": { - "app_layout_menu_code_to_inject/1:169": { - "line": 169, - "guard": null, - "pattern": "x0", - "kind": "def", - "end_line": 169, - "ast_sha": "ad56e90842058c640e06e88b10d90c9eed8a10b1ba03e0f83e77c61b87137ca7", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "9ed11f34e2931aede8d9e63e63a87548d7d728894f81675fa9557763ca3ca2c2", - "start_line": 169, - "name": "app_layout_menu_code_to_inject", - "arity": 1 - }, - "app_layout_menu_code_to_inject/2:169": { - "line": 169, - "guard": null, - "pattern": "x0, x1", - "kind": "def", - "end_line": 169, - "ast_sha": "78dff31dfabe16af5ad2a9972739c7f9b19847bfaccc90817456ebed80703fac", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "9ed11f34e2931aede8d9e63e63a87548d7d728894f81675fa9557763ca3ca2c2", - "start_line": 169, - "name": "app_layout_menu_code_to_inject", - "arity": 2 - }, - "app_layout_menu_code_to_inject/3:169": { - "line": 169, - "guard": null, - "pattern": "binding, padding, newline", - "kind": "def", - "end_line": 197, - "ast_sha": "ded110cef010fdfc38f11f4bed247a24e1ef90f09a4e730c2756e464a92e99bc", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "27fa4712fae262d2956e5119554651abd2a6d9a314f85d02df92abc5dc0d1ef1", - "start_line": 169, - "name": "app_layout_menu_code_to_inject", - "arity": 3 - }, - "app_layout_menu_help_text/2:156": { - "line": 156, - "guard": null, - "pattern": "file_path, binding", - "kind": "def", - "end_line": 162, - "ast_sha": "a2cf1ffd60566e47b9b7f1decd4dbf4da5bb6f1a123a990f14a5904ab355e67b", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "cdec6898ad330d0192754df2629348b06436ad4b302ebc4cea0fc08a10eee7c9", - "start_line": 156, - "name": "app_layout_menu_help_text", - "arity": 2 - }, - "app_layout_menu_inject/2:144": { - "line": 144, - "guard": null, - "pattern": "binding, template_str", - "kind": "def", - "end_line": 148, - "ast_sha": "1e9606ac71d2dbfeca2bec28458cfddf21ba7e0034576b9ce9b91f4bf36ceee3", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "a6ebaffff74be7028fd7c712d915e59a68f46a7f225776b377931fc7578dcfa8", - "start_line": 144, - "name": "app_layout_menu_inject", - "arity": 2 - }, - "app_layout_menu_inject_after_opening_body_tag/2:223": { - "line": 223, - "guard": null, - "pattern": "binding, file", - "kind": "defp", - "end_line": 237, - "ast_sha": "f45e2b2f629e4acfb33b169ecbfff118921793a240634797367794ed7cb5c36e", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "fdd8715feccf71ee3ac152647a0f383f955560418715e615b737db3fef47edff", - "start_line": 223, - "name": "app_layout_menu_inject_after_opening_body_tag", - "arity": 2 - }, - "app_layout_menu_inject_at_end_of_nav_tag/2:211": { - "line": 211, - "guard": null, - "pattern": "binding, file", - "kind": "defp", - "end_line": 219, - "ast_sha": "fc05fdbd4517daf9f3e2e9259d2e7853a6dbb0d966654257ab0ac06895b82c4a", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "71cd5ec4ab9606bc7f7db2c6f5c1a13ecf78f1e31f0155d8058cc04dd9fc4b9e", - "start_line": 211, - "name": "app_layout_menu_inject_at_end_of_nav_tag", - "arity": 2 - }, - "config_inject/2:44": { - "line": 44, - "guard": "is_binary(file) and is_binary(code_to_inject)", - "pattern": "file, code_to_inject", - "kind": "def", - "end_line": 54, - "ast_sha": "da803c617bab73917b93aef2e22b000d6e3f2a68c7d183da320d085db49f3ebb", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "2252639c24a3c58a50ce623b56286e81c351fbd97a623268204f839487dc18eb", - "start_line": 44, - "name": "config_inject", - "arity": 2 - }, - "do_mix_dependency_inject/2:23": { - "line": 23, - "guard": null, - "pattern": "mixfile, dependency", - "kind": "defp", - "end_line": 36, - "ast_sha": "fa78bc38fe429e7a88e00275f37a5a764a9789d1143374290efadf088d34c7f8", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "a0ef670a317d9d753d935769e680f5876cc0904e0db2692ce47538a797803419", - "start_line": 23, - "name": "do_mix_dependency_inject", - "arity": 2 - }, - "ensure_not_already_injected/2:283": { - "line": 283, - "guard": null, - "pattern": "file, inject", - "kind": "defp", - "end_line": 284, - "ast_sha": "ce28be63a0fcda30ce402ae8cd0abcc4413d96915b14695ac1a51f7f41fc6a33", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "e70c7c7c75de8aa12204467de69a9191160a23a627b9f39fac84cff8c7fb4b08", - "start_line": 283, - "name": "ensure_not_already_injected", - "arity": 2 - }, - "formatting_info/2:200": { - "line": 200, - "guard": null, - "pattern": "template, tag", - "kind": "defp", - "end_line": 208, - "ast_sha": "e1454f89976b09b407581ad580639f9e77942c8f69b143437eb4dce71f080c6f", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "b8cabed576281458b7121c945b78bc21343cf8f8895d739067bfa676c8e48a1c", - "start_line": 200, - "name": "formatting_info", - "arity": 2 - }, - "get_line_ending/1:305": { - "line": 305, - "guard": null, - "pattern": "file", - "kind": "defp", - "end_line": 308, - "ast_sha": "c8d78e0df286185b62f59c3741a0e136cd0c840483308f4f57282513d061a57e", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "593ad4a6b643eec7152e1de820ec0c6798ba1bbb959017b7652760f95975198b", - "start_line": 305, - "name": "get_line_ending", - "arity": 1 - }, - "indent_spaces/2:312": { - "line": 312, - "guard": null, - "pattern": "x0, x1", - "kind": "defp", - "end_line": 312, - "ast_sha": "dbbe4566298fd1bf5b43b3e9f518ffc0978376df1e51b3bec1d971a693c168e6", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "2954e8656d3f7816922b162ba40ab240cc2d5fbfa258abeef93c690d702bff59", - "start_line": 312, - "name": "indent_spaces", - "arity": 2 - }, - "indent_spaces/3:312": { - "line": 312, - "guard": "is_binary(string) and is_integer(number_of_spaces)", - "pattern": "string, number_of_spaces, newline", - "kind": "defp", - "end_line": 318, - "ast_sha": "ffe50878da165fdfa2a76274aa6bc36348d5a95f24ab29b7116c2b606128ad8a", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "1dd240ef8d51348305742dba2a26329ee603ee2a5b8732a8ee5c8f076b21da6c", - "start_line": 312, - "name": "indent_spaces", - "arity": 3 - }, - "inject_before_final_end/2:266": { - "line": 266, - "guard": "is_binary(code) and is_binary(code_to_inject)", - "pattern": "code, code_to_inject", - "kind": "def", - "end_line": 278, - "ast_sha": "4e9119ab1976b162ee90d94557244edc7200182a177bef2a8f16f75ec8817c49", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "5b5c989bf04b2eaa81591118f73e796f1b971be924233813103e20f4c7180cb8", - "start_line": 266, - "name": "inject_before_final_end", - "arity": 2 - }, - "inject_unless_contains/3:244": { - "line": 244, - "guard": null, - "pattern": "code, dup_check, inject_fn", - "kind": "def", - "end_line": 245, - "ast_sha": "4cf3ba333b128433fd0b77ba03d1aed1c1acbb27b2cf5495df7784055b7f191f", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "a80b2e88113f15b67ddb5afa1b1c0afa84a72db1a9296ea94039f63cdd71d1e7", - "start_line": 244, - "name": "inject_unless_contains", - "arity": 3 - }, - "inject_unless_contains/4:248": { - "line": 248, - "guard": "is_binary(code) and is_binary(code_to_inject) and is_binary(dup_check) and\n is_function(inject_fn, 2)", - "pattern": "code, dup_check, code_to_inject, inject_fn", - "kind": "def", - "end_line": 255, - "ast_sha": "b750cb9d257368ca9ece94aa1c1b4cfb8385e10147922c74dc47cafdfd16a415", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "52ecaccf006ebb903f9f58a0c73fdbf891feae986aadcae1a1ee7d4ca736001f", - "start_line": 248, - "name": "inject_unless_contains", - "arity": 4 - }, - "mix_dependency_inject/2:14": { - "line": 14, - "guard": null, - "pattern": "mixfile, dependency", - "kind": "def", - "end_line": 17, - "ast_sha": "a230f3fccefd744a21a417521bec74c8d93cdb9f9464730507e77cb28ff78cf2", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "1ad7e915e97253561e1c6be84ae3208b99eea32d51e6023d76e1d0487cdfbd55", - "start_line": 14, - "name": "mix_dependency_inject", - "arity": 2 - }, - "normalize_line_endings_to_file/2:300": { - "line": 300, - "guard": null, - "pattern": "code, file", - "kind": "defp", - "end_line": 301, - "ast_sha": "2c4b70756190c3d1c3ac11703f8ded92077519d8c42e88b5e7a1ce3b6b6df5d7", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "ca50b9b5f2c32f0303fd9d9ca116329672d78a07bb26000a0d05f9a5e5dddbb8", - "start_line": 300, - "name": "normalize_line_endings_to_file", - "arity": 2 - }, - "router_plug_code/1:133": { - "line": 133, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 134, - "ast_sha": "a0feded73cab800b3ce5f5f6be1c174c5fd4b186335bdede455eb94bf29c6415", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "0eaf0c486f5e52e5d8001cec2e22dda7eeec569196e9bbf3196471bdb5763ab1", - "start_line": 133, - "name": "router_plug_code", - "arity": 1 - }, - "router_plug_help_text/2:121": { - "line": 121, - "guard": null, - "pattern": "file_path, binding", - "kind": "def", - "end_line": 128, - "ast_sha": "0624feb7ab1f450dfc540f3af9e3141efbd1cbcdf958ff194f135792a8319542", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "86ded1f1e178839d95f7c2cbabeaae001cf8a1956d604a983540f473bf22013c", - "start_line": 121, - "name": "router_plug_help_text", - "arity": 2 - }, - "router_plug_inject/2:100": { - "line": 100, - "guard": "is_binary(file)", - "pattern": "file, binding", - "kind": "def", - "end_line": 111, - "ast_sha": "49b4479dd68fedc56a2a2237e30a0650fe4c7b0b347cc3773c335247dfd895e1", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "e09fc1621d18bd99ebc46985d6c457925ad5956ecdf086ce0662d5743a4d680d", - "start_line": 100, - "name": "router_plug_inject", - "arity": 2 - }, - "router_plug_name/1:137": { - "line": 137, - "guard": null, - "pattern": "binding", - "kind": "defp", - "end_line": 138, - "ast_sha": "4b6f4e014a4e1f3ce4b1a2c36dbdc9565db7bc50d2e4e416c3789b9eb97b2608", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "fc18e3e0a15c3a9690eab9b6c9c56472d8a7601462aac44642f0f3a3a0981d9a", - "start_line": 137, - "name": "router_plug_name", - "arity": 1 - }, - "split_with_self/2:292": { - "line": 292, - "guard": null, - "pattern": "contents, text", - "kind": "defp", - "end_line": 295, - "ast_sha": "3141c1636c63d8b665130e69a25e7ae3bf13a5c5f180d4e43b513d62de540bb5", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "29fb79d2a2386fbe171d94503bd3c5702c6ebed39be0c55476c3dad22fd44bf7", - "start_line": 292, - "name": "split_with_self", - "arity": 2 - }, - "test_config_code/1:86": { - "line": 86, - "guard": null, - "pattern": "%Mix.Tasks.Phx.Gen.Auth.HashingLibrary{test_config: test_config}", - "kind": "defp", - "end_line": 89, - "ast_sha": "d5bff2421c0aea67bac65427e798253074cdad7989e81b7bef23c11c4eaf4a0d", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "2318fd8f04c58f32ec9753ace7949440af049c86b1ea77203202952587b05007", - "start_line": 86, - "name": "test_config_code", - "arity": 1 - }, - "test_config_help_text/2:78": { - "line": 78, - "guard": null, - "pattern": "file_path, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", - "kind": "def", - "end_line": 82, - "ast_sha": "c5d70d02cabdbd429bbb7c060bb6398b6a96d61142dcdb7c898619e44c35ca42", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "e2cb79ec6ac7e7d6199776bc16463db84a9ae7571d5a898c04f43575ba8d4353", - "start_line": 78, - "name": "test_config_help_text", - "arity": 2 - }, - "test_config_inject/2:65": { - "line": 65, - "guard": "is_binary(file)", - "pattern": "file, %Mix.Tasks.Phx.Gen.Auth.HashingLibrary{} = hashing_library", - "kind": "def", - "end_line": 71, - "ast_sha": "901651af7cdc1e371caef478bb52bf15d2d2e39b21fcb28cada0c23b41c4ce74", - "source_file": "lib/mix/tasks/phx.gen.auth/injector.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/injector.ex", - "source_sha": "c72c42245f3de9bcf290f3e6767cd8cd7d90ec396410c927a3a9b947032d4747", - "start_line": 65, - "name": "test_config_inject", - "arity": 2 - } - }, - "Mix.Tasks.Phx": { - "general/0:32": { - "line": 32, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 38, - "ast_sha": "3050070af5a1364e13c0150b65c334bf963a313adbca59d547a8d59e500ba05e", - "source_file": "lib/mix/tasks/phx.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", - "source_sha": "b0e1d22add9d555918e449af9dae3768f1e18eace30d3bff167b73b8a05fdd44", - "start_line": 32, - "name": "general", - "arity": 0 - }, - "run/1:21": { - "line": 21, - "guard": "=:=(version, \"-v\") or =:=(version, \"--version\")", - "pattern": "[version]", - "kind": "def", - "end_line": 22, - "ast_sha": "027b701f2c254592bca06521c00af7f6651026d61451b28fe958a1c243bb2730", - "source_file": "lib/mix/tasks/phx.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", - "source_sha": "d3a22d33b7729da940a6b0253d6d17c283dbe56b02d78dddf4f405800b05a652", - "start_line": 21, - "name": "run", - "arity": 1 - }, - "run/1:25": { - "line": 25, - "guard": null, - "pattern": "args", - "kind": "def", - "end_line": 28, - "ast_sha": "96c16fc40ec19ed7ebbf484e08b5bc7cecd51c1d0d4bd281086e1e81e3d1a8d6", - "source_file": "lib/mix/tasks/phx.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.ex", - "source_sha": "e5b9618eb03792eaa310e3081b48b36039ae6ad03ff3aea26b54e676c337de7e", - "start_line": 25, - "name": "run", - "arity": 1 - } - }, - "Phoenix.Router.Resource": { - "__struct__/0:24": { - "line": 24, - "guard": null, - "pattern": "", - "kind": "def", - "end_line": 24, - "ast_sha": "3ddf9201601595adc9c5382b6b96cb6fe37c9516c3f2c6086b2cbc40122cbb76", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "4acb922e7c1776213c3cb445b245cb41a12e0d007664de3dde5d31f8dc5878fa", - "start_line": 24, - "name": "__struct__", - "arity": 0 - }, - "__struct__/1:24": { - "line": 24, - "guard": null, - "pattern": "kv", - "kind": "def", - "end_line": 24, - "ast_sha": "4b1f9c53dcab7f9debd09f66c76b081723e0a4965841daadfe33d70450747076", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "4acb922e7c1776213c3cb445b245cb41a12e0d007664de3dde5d31f8dc5878fa", - "start_line": 24, - "name": "__struct__", - "arity": 1 - }, - "build/3:30": { - "line": 30, - "guard": "is_atom(controller) and is_list(options)", - "pattern": "path, controller, options", - "kind": "def", - "end_line": 48, - "ast_sha": "7fe608085a0b7bd90c0fc670c11a2d3fc50195fec42747a6b7d8a15c6186d172", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "b3f3ad3044a512f07353a67ab30f449ab8427bb284b40ad87ef1398488a0b256", - "start_line": 30, - "name": "build", - "arity": 3 - }, - "default_actions/1:84": { - "line": 84, - "guard": null, - "pattern": "true = _singleton", - "kind": "defp", - "end_line": 84, - "ast_sha": "e155983070e2569b4e303fada5cff1c587a6eaa12201c0fc21e47d0b04fe7f79", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "1936fdc53d44a6f7427be4689c69c57f7d58fcea86ad9971012874078bd5e173", - "start_line": 84, - "name": "default_actions", - "arity": 1 - }, - "default_actions/1:85": { - "line": 85, - "guard": null, - "pattern": "false = _singleton", - "kind": "defp", - "end_line": 85, - "ast_sha": "9db9839a268d7a735cd8a68d193f10bf8306b51cd8de24f49983a1311757da7b", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "fcca3764db6546033df3806297e766e0d9831eb3eeedd51375bc26e498d7bbee", - "start_line": 85, - "name": "default_actions", - "arity": 1 - }, - "extract_actions/2:51": { - "line": 51, - "guard": null, - "pattern": "opts, singleton", - "kind": "defp", - "end_line": 64, - "ast_sha": "ab48fb60d8137258856f6b2d72c384ae07fd1d9bd455a3174cc7f41a04b79557", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "d4d01282a50fc1e65478bc10d859ba4d02ff1f9236802b7db72b387d9be4dea5", - "start_line": 51, - "name": "extract_actions", - "arity": 2 - }, - "validate_actions/3:68": { - "line": 68, - "guard": null, - "pattern": "type, singleton, actions", - "kind": "defp", - "end_line": 81, - "ast_sha": "af46cfe7794910fb10bdb9c17877ec52c1580876ee39028412806e9e618b210d", - "source_file": "lib/phoenix/router/resource.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/phoenix/router/resource.ex", - "source_sha": "23bfd893d56fc6fd89140491e3bd34e84f9bdd7fb7872bcd0cfc9584f900cfae", - "start_line": 68, - "name": "validate_actions", - "arity": 3 - } - }, - "Mix.Tasks.Phx.Gen.Cert": { - "basic_constraints/0:204": { - "line": 204, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 204, - "ast_sha": "0e681c5f76ea7716ee05cc37312eb06916b2035387308fa4c27ad1607a14f972", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 204, - "name": "basic_constraints", - "arity": 0 - }, - "basic_constraints/2:204": { - "line": 204, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 204, - "ast_sha": "afebfff5873c271f9c083ff0fbd7e9a31cf4c7107048f627b3026f396d7a2d1b", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 204, - "name": "basic_constraints", - "arity": 2 - }, - "rsa_public_key/0:148": { - "line": 148, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 148, - "ast_sha": "ba1337896a45e0cc9f1b1bc8606d6e32f3789c720c6bd721d8293747a13ce3e9", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 148, - "name": "rsa_public_key", - "arity": 0 - }, - "validity/2:180": { - "line": 180, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 180, - "ast_sha": "0be112fc7c8f43d8a5a52a0f18ee7f755c6dce47fcd922bdf4e2b3341c41aa78", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 180, - "name": "validity", - "arity": 2 - }, - "certificate_and_key/3:89": { - "line": 89, - "guard": null, - "pattern": "key_size, name, hostnames", - "kind": "def", - "end_line": 112, - "ast_sha": "c5e5afa09f7cce0eb249e0d31458ab02a275d894b91ce5912fc53d8650aea50d", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "61be263fb1fd329dafd03051a8f9445f895a2b6a5208234acb8148a1cb4bcdc4", - "start_line": 89, - "name": "certificate_and_key", - "arity": 3 - }, - "otp_subject_public_key_info/1:186": { - "line": 186, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 186, - "ast_sha": "fa1600c0e011f556ee1a52849fc5649c636e7162e391279e256b66e50bd97e64", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 186, - "name": "otp_subject_public_key_info", - "arity": 1 - }, - "otp_tbs_certificate/1:168": { - "line": 168, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 168, - "ast_sha": "ddcb3437b28d0297f2d657643667ee9c04c30ae8ac1c2c27b9b3c3e168d56bdb", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 168, - "name": "otp_tbs_certificate", - "arity": 1 - }, - "key_identifier/1:306": { - "line": 306, - "guard": null, - "pattern": "public_key", - "kind": "defp", - "end_line": 307, - "ast_sha": "010dff7eeb82e0080cd0acdda8e451d3e2ae12363eda168350d07c814ce9e119", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "d22d93c3bbe121892419a94944a342125909d67356dd006fc275705ace46a83a", - "start_line": 306, - "name": "key_identifier", - "arity": 1 - }, - "extract_public_key/1:162": { - "line": 162, - "guard": null, - "pattern": "{:RSAPrivateKey, _, m, e, _, _, _, _, _, _, _}", - "kind": "defp", - "end_line": 163, - "ast_sha": "62f6e580c26fde55069992dc796eb8a6d1b6525ab48ab0508979b5bea77404c0", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "2e741bffc189dd0fd3db7f585a6a54fcfd5332bbee6e5e6d89611be5302f941d", - "start_line": 162, - "name": "extract_public_key", - "arity": 1 - }, - "generate_rsa_key/2:154": { - "line": 154, - "guard": null, - "pattern": "keysize, e", - "kind": "defp", - "end_line": 158, - "ast_sha": "37c104b29040b16e0760fbe9132c715cd5b3609d317d1046d19010e52ae422c4", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "276c9910cd9306d31978c64c19aba8cc2f6a750b736d976f7e386df272c71b90", - "start_line": 154, - "name": "generate_rsa_key", - "arity": 2 - }, - "otp_subject_public_key_info/0:186": { - "line": 186, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 186, - "ast_sha": "17aaba81a3ace80415638f73469812c98bcf4b0cf1fc8d4ca3762c6092c0ebf6", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 186, - "name": "otp_subject_public_key_info", - "arity": 0 - }, - "basic_constraints/1:204": { - "line": 204, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 204, - "ast_sha": "e35f671b29b21ca8b8936d3165c0dbc24aba9ad0139eeceffcd7aa6869a90143", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 204, - "name": "basic_constraints", - "arity": 1 - }, - "otp_subject_public_key_info/2:186": { - "line": 186, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 186, - "ast_sha": "30f7303f1b82b94408253158c8024054209ebda1d89af40db19997c35e5f39a8", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 186, - "name": "otp_subject_public_key_info", - "arity": 2 - }, - "rsa_private_key/1:142": { - "line": 142, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 142, - "ast_sha": "38e82ed04d99a260c0a6a53b7f5e7aeea7394b0404f2b92672ca8f8500fbea70", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 142, - "name": "rsa_private_key", - "arity": 1 - }, - "extensions/2:276": { - "line": 276, - "guard": null, - "pattern": "public_key, hostnames", - "kind": "defp", - "end_line": 301, - "ast_sha": "ea4aeaed45b7923570f88b9ef9ce060a67480bdabc14210bd2dadcd4ceeee84e", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "31e79ba3a3d28ea17ba9e1026f8bde8de68fe6513cd1257f527fa545da29aec6", - "start_line": 276, - "name": "extensions", - "arity": 2 - }, - "run/1:47": { - "line": 47, - "guard": null, - "pattern": "all_args", - "kind": "def", - "end_line": 85, - "ast_sha": "643f2603b375c3a3f1cb90b8e1c62155d7a465f3332c7a17b91ee3aafbb320b8", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "e85bcaec49d8f3c522412772dbc7d9937a4f4594cd1c755b1094f66ac8e1748d", - "start_line": 47, - "name": "run", - "arity": 1 - }, - "public_key_algorithm/2:192": { - "line": 192, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 192, - "ast_sha": "bbaa200c4323e0c9ed708ce49bc37af567df1589cc26a8577595b23b49ac1bc1", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 192, - "name": "public_key_algorithm", - "arity": 2 - }, - "signature_algorithm/1:174": { - "line": 174, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 174, - "ast_sha": "de6ab0e51d7462030c7f86d32ccc47c41f3d5ae822a20ce85bb6932964410c5a", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 174, - "name": "signature_algorithm", - "arity": 1 - }, - "otp_tbs_certificate/0:168": { - "line": 168, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 168, - "ast_sha": "73895694168a0d9fee58eb586be5f8ae8d6a3a51f64c79f3015b6e05425be967", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 168, - "name": "otp_tbs_certificate", - "arity": 0 - }, - "new_cert/3:232": { - "line": 232, - "guard": null, - "pattern": "public_key, common_name, hostnames", - "kind": "defp", - "end_line": 264, - "ast_sha": "d3173971e37eda060104e0a236e315d1700e5bc43a44266be19ee2568866e16b", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "1cb5f21dfa5b6cd7afce71b3433872431564de873e18f1d0b5c4debf1e43ceb8", - "start_line": 232, - "name": "new_cert", - "arity": 3 - }, - "extension/2:198": { - "line": 198, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 198, - "ast_sha": "0fbcfcc76b57a45d3e6efd9960c10271e3fa2cf6b5595facce1d0908f5fd4597", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 198, - "name": "extension", - "arity": 2 - }, - "rdn/1:268": { - "line": 268, - "guard": null, - "pattern": "common_name", - "kind": "defp", - "end_line": 272, - "ast_sha": "a7073dd3f3743af67d11cc80afca00f100b49901909b4d2fda4ffb9c8256ead3", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "568717d5125a101f2a46ac1c4993824bc44366f64c787a2c1932471b9fd8cf5c", - "start_line": 268, - "name": "rdn", - "arity": 1 - }, - "public_key_algorithm/1:192": { - "line": 192, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 192, - "ast_sha": "eb7dca39114d26e46500b59a929b86ed27de738edfa69ecabc97de93352d8a01", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 192, - "name": "public_key_algorithm", - "arity": 1 - }, - "rsa_private_key/0:142": { - "line": 142, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 142, - "ast_sha": "500965ae58c255135fb78c62cf008d9797954ed6c95e77753d8769cd2851a2f0", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 142, - "name": "rsa_private_key", - "arity": 0 - }, - "otp_tbs_certificate/2:168": { - "line": 168, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 168, - "ast_sha": "df88a26d037db383a1c36b3987b7690f19091f114fee687ab0635d6e2c4fc582", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 168, - "name": "otp_tbs_certificate", - "arity": 2 - }, - "attr/0:210": { - "line": 210, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 210, - "ast_sha": "625230d22c289c5aa1383fdaa579c581729fa5e133ecae632cd393a2c43a6499", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 210, - "name": "attr", - "arity": 0 - }, - "public_key_algorithm/0:192": { - "line": 192, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 192, - "ast_sha": "228109cd362d755c0a50f72ce05b4d61a995d115b21f007f1cecf87dbd7c0c0b", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 192, - "name": "public_key_algorithm", - "arity": 0 - }, - "rsa_private_key/2:142": { - "line": 142, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 142, - "ast_sha": "3edbc0033af63843611154e902709454cfa119e7093f2c13cbf4d7cf9f675983", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 142, - "name": "rsa_private_key", - "arity": 2 - }, - "extension/0:198": { - "line": 198, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 198, - "ast_sha": "5f5393831ff7a6476dc4ea7a13906726d350734b92a5ae0076ed25bad36bbb32", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 198, - "name": "extension", - "arity": 0 - }, - "signature_algorithm/0:174": { - "line": 174, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 174, - "ast_sha": "73d7a989e803f0837fea886b4208eeff7f65f3fcb2e0caafeef7e7d4bcc4b18d", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 174, - "name": "signature_algorithm", - "arity": 0 - }, - "rsa_public_key/2:148": { - "line": 148, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 148, - "ast_sha": "f323a2417ecbba07797688a77b48521161380f9640247d363c503789a2e882fe", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 148, - "name": "rsa_public_key", - "arity": 2 - }, - "print_shell_instructions/2:115": { - "line": 115, - "guard": null, - "pattern": "keyfile, certfile", - "kind": "defp", - "end_line": 134, - "ast_sha": "6b4bcd0cb3eb21d39e0f32c64412a35325bc656904fcca46b1e6fadfb8d3eaf1", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "92f856175238411994c4da6817139742e90a1214f7e96d906a32fc4dcc3677aa", - "start_line": 115, - "name": "print_shell_instructions", - "arity": 2 - }, - "extension/1:198": { - "line": 198, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 198, - "ast_sha": "3f008778390d565523fea784ae4defa3be2f22b55090b4d8ffcc2ecdd959cea3", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 198, - "name": "extension", - "arity": 1 - }, - "validity/1:180": { - "line": 180, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 180, - "ast_sha": "d60be99887e0144b243c122e026d4db48f74ac2f14a6337bbf249fd508fb5d28", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 180, - "name": "validity", - "arity": 1 - }, - "validity/0:180": { - "line": 180, - "guard": null, - "pattern": "", - "kind": "defmacrop", - "end_line": 180, - "ast_sha": "4f8a8a6d27025844b936da3ee67721542bc7fe371c731ac8a135caa4c36187e4", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 180, - "name": "validity", - "arity": 0 - }, - "rsa_public_key/1:148": { - "line": 148, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 148, - "ast_sha": "6a795dfc40ee1ece67316a96e3cb1ba63ed56059b0dfcbe86db0887c48966d7b", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 148, - "name": "rsa_public_key", - "arity": 1 - }, - "attr/1:210": { - "line": 210, - "guard": null, - "pattern": "args", - "kind": "defmacrop", - "end_line": 210, - "ast_sha": "8d72c41dd33c05326e2374fa9f2b20bb35bd5e349a780d4fe633558e32e9b251", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 210, - "name": "attr", - "arity": 1 - }, - "attr/2:210": { - "line": 210, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 210, - "ast_sha": "c266007d671940dd394527b8f8d665ffb291ba7526f0dae322f2fec0b2993afb", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 210, - "name": "attr", - "arity": 2 - }, - "signature_algorithm/2:174": { - "line": 174, - "guard": null, - "pattern": "record, args", - "kind": "defmacrop", - "end_line": 174, - "ast_sha": "0c80c94bf2d7bb596cd2cc553810da1510e668f4f61aec139f53818527505ca5", - "source_file": "lib/mix/tasks/phx.gen.cert.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.cert.ex", - "source_sha": "37444e68c265cc214748f6ec5864cebf6630c7b665338c9afc54ea71d46aa24c", - "start_line": 174, - "name": "signature_algorithm", - "arity": 2 - } - }, - "Mix.Tasks.Phx.Gen.Auth.Migration": { - "build/1:6": { - "line": 6, - "guard": "is_atom(ecto_adapter)", - "pattern": "ecto_adapter", - "kind": "def", - "end_line": 10, - "ast_sha": "cec9dcf8ae7824ea58b7ebac4759c88e30181fe3313d7ad58de4be701b9d56a3", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "32fc3f86439149c0030698a01854f419ddfafd4cfe27941a5dcea665dbbf839c", - "start_line": 6, - "name": "build", - "arity": 1 - }, - "column_definition/2:26": { - "line": 26, - "guard": null, - "pattern": ":email, Ecto.Adapters.Postgres", - "kind": "defp", - "end_line": 26, - "ast_sha": "8a5c262d3e0d66ed3da62d0f3b03fe3e4eeed107ee1055791c97aa75d4b50b6e", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "7710259ae2884c5cd67fed5e75e4383fe7775432446cb6cc2ef3b74b4d9e8f43", - "start_line": 26, - "name": "column_definition", - "arity": 2 - }, - "column_definition/2:27": { - "line": 27, - "guard": null, - "pattern": ":email, Ecto.Adapters.SQLite3", - "kind": "defp", - "end_line": 27, - "ast_sha": "2b2b4ba617e07e0127679364205f2bca5fda542857b2e1e8d6c7e431a0860a98", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "d76e5bdc06cc12c246e5e0bf5a442ca55837b3ac6fe063d1f987cd3d786e4e2b", - "start_line": 27, - "name": "column_definition", - "arity": 2 - }, - "column_definition/2:28": { - "line": 28, - "guard": null, - "pattern": ":email, _", - "kind": "defp", - "end_line": 28, - "ast_sha": "db12d52853ef14fd7a7946cfa8d0238896aacde28221325a3c85d859b73014fe", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "6c1484d6bde44bfd3a8510d4ab57137813b9577ae4382f25b2c05e52c3f75355", - "start_line": 28, - "name": "column_definition", - "arity": 2 - }, - "column_definition/2:30": { - "line": 30, - "guard": null, - "pattern": ":token, Ecto.Adapters.Postgres", - "kind": "defp", - "end_line": 30, - "ast_sha": "0ca658a6040b6c3f6585a6ac6a5057e3ba8198e9afc40cd38a31301a9e5d1264", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "b15d5b4491d4bc08efef9cbd9e21b1a3fc0d9c402acd747c24d09ae03831c240", - "start_line": 30, - "name": "column_definition", - "arity": 2 - }, - "column_definition/2:32": { - "line": 32, - "guard": null, - "pattern": ":token, _", - "kind": "defp", - "end_line": 32, - "ast_sha": "9efd730eccff08203aec7707c4240dad86872a866a9aad459d942a9bee3f1ebf", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "b067d21e5256ee508b8f9f48f0f72bbdae7977e3d9aed4067d92b5b2daca135a", - "start_line": 32, - "name": "column_definition", - "arity": 2 - }, - "column_definitions/1:20": { - "line": 20, - "guard": null, - "pattern": "ecto_adapter", - "kind": "defp", - "end_line": 23, - "ast_sha": "ccee25ebc00c54e7e9058d4240b6b9e496c910175780f8bffd981d3b5283abe7", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "1a8097771411acc16cedd840b0fe82f8f790e68f7e5de49aa7f5ec428e559c67", - "start_line": 20, - "name": "column_definitions", - "arity": 1 - }, - "extensions/1:14": { - "line": 14, - "guard": null, - "pattern": "Ecto.Adapters.Postgres", - "kind": "defp", - "end_line": 14, - "ast_sha": "81b4cabe530f0b5287c97fc7e73770176087b23f2f54b354421e3d04e9e138e1", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "72e4d89dc89a89f2287bbbde75f644820c65a8b628f194f5393fd8441433376d", - "start_line": 14, - "name": "extensions", - "arity": 1 - }, - "extensions/1:18": { - "line": 18, - "guard": null, - "pattern": "_", - "kind": "defp", - "end_line": 18, - "ast_sha": "cd9a1ecf3037be6bf542dbbbf970b1538abea2533a8a8759803a3870342601ce", - "source_file": "lib/mix/tasks/phx.gen.auth/migration.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.auth/migration.ex", - "source_sha": "e721aac73af1bba172ba4cd86bddde34d2c9a8344857f3f8c9ecc4aea3139d0b", - "start_line": 18, - "name": "extensions", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Gen.Presence": { - "paths/0:66": { - "line": 66, - "guard": null, - "pattern": "", - "kind": "defp", - "end_line": 66, - "ast_sha": "b4355323a83427651573e0f226a58d2ac5f20632ef9f1938f974afe09b44efb9", - "source_file": "lib/mix/tasks/phx.gen.presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "source_sha": "99a8db045c0caa63597e348bd9938f84f47d5b07cbcdd6d98f45f282fe55d479", - "start_line": 66, - "name": "paths", - "arity": 0 - }, - "run/1:19": { - "line": 19, - "guard": null, - "pattern": "[]", - "kind": "def", - "end_line": 20, - "ast_sha": "c1f727852ef6d0e1f908a1361b772ce15f70de5a4dc4358097f461f5cb280139", - "source_file": "lib/mix/tasks/phx.gen.presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "source_sha": "d8e2875d64949f609af7e416af492920048c9431328297452734754d74e5fc54", - "start_line": 19, - "name": "run", - "arity": 1 - }, - "run/1:23": { - "line": 23, - "guard": null, - "pattern": "[alias_name]", - "kind": "def", - "end_line": 58, - "ast_sha": "ff0fdec2fd73ccde273823c19183029d2a4bbf2143e69d79c6e38352fb937416", - "source_file": "lib/mix/tasks/phx.gen.presence.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.gen.presence.ex", - "source_sha": "d607e4fe106896a27c0e93886ae8d9cd89f3e09a366f2e5cf8ebf125ff40b308", - "start_line": 23, - "name": "run", - "arity": 1 - } - }, - "Mix.Tasks.Phx.Digest.Clean": { - "run/1:43": { - "line": 43, - "guard": null, - "pattern": "all_args", - "kind": "def", - "end_line": 73, - "ast_sha": "f54e6551186ad42c4d8835d77c9a54a964e198253fac6e56818180da680a9baf", - "source_file": "lib/mix/tasks/phx.digest.clean.ex", - "source_file_absolute": "/Users/camonz/Code/phoenix/lib/mix/tasks/phx.digest.clean.ex", - "source_sha": "cce93f3b4b0920f70c578b4f7e84e42bc805dec5085b8be4121c2985204515a2", - "start_line": 43, - "name": "run", - "arity": 1 - } - } - }, - "types": { - "Phoenix.Logger": [], - "Mix.Tasks.Phx.Gen.Notifier": [], - "Phoenix.Channel": [ - { - "line": 341, - "name": "socket_ref", - "params": [], - "kind": "type", - "definition": "@type socket_ref() :: {Pid, module(), binary(), binary(), binary()}" - }, - { - "line": 340, - "name": "reply", - "params": [], - "kind": "type", - "definition": "@type reply() :: atom() | {atom(), payload()}" - }, - { - "line": 339, - "name": "payload", - "params": [], - "kind": "type", - "definition": "@type payload() :: map() | term() | {:binary, binary()}" - } - ], - "Phoenix.Channel.Server": [], - "Phoenix.Socket.PoolDrainer": [], - "Phoenix.Controller": [ - { - "line": 16, - "name": "layout", - "params": [], - "kind": "type", - "definition": "@type layout() :: {module(), atom()} | false" - }, - { - "line": 15, - "name": "view", - "params": [], - "kind": "type", - "definition": "@type view() :: atom()" - } - ], - "Phoenix.Param.Float": [], - "Phoenix.Endpoint.Watcher": [], - "Mix.Tasks.Phx.Gen.Socket": [], - "Mix.Tasks.Phx.Gen.Auth.HashingLibrary": [ - { - "line": 6, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Mix.Tasks.Phx.Gen.Auth.HashingLibrary, mix_dependency: binary(), module: module(), name: atom(), test_config: binary()}" - } - ], - "Phoenix.Router.NoRouteError": [], - "Phoenix.Router.Helpers": [], - "Phoenix.CodeReloader.Proxy": [], - "Phoenix.ActionClauseError": [], - "Phoenix.Socket": [ - { - "line": 273, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Socket, assigns: map(), channel: atom(), channel_pid: pid(), endpoint: atom(), handler: atom(), id: String.t() | nil, join_ref: term(), joined: boolean(), private: map(), pubsub_server: atom(), ref: term(), serializer: atom(), topic: String.t(), transport: atom(), transport_pid: pid()}" - } - ], - "Phoenix.Digester.Gzip": [], - "Phoenix": [], - "Mix.Tasks.Phx.Gen.Channel": [], - "Phoenix.Socket.Transport": [ - { - "line": 99, - "name": "state", - "params": [], - "kind": "type", - "definition": "@type state() :: term()" - } - ], - "Phoenix.Naming": [], - "Phoenix.Flash": [], - "Phoenix.Param": [ - { - "line": 1, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: term()" - } - ], - "Mix.Tasks.Phx.Gen": [], - "Mix.Tasks.Phx.Gen.Embedded": [], - "Mix.Tasks.Phx.Gen.Schema": [], - "Phoenix.Socket.Serializer": [], - "Mix.Tasks.Phx.Digest": [], - "Mix.Tasks.Phx.Gen.Html": [], - "Phoenix.Param.Integer": [], - "Phoenix.Endpoint": [ - { - "line": 281, - "name": "msg", - "params": [], - "kind": "type", - "definition": "@type msg() :: map() | {:binary, binary()}" - }, - { - "line": 280, - "name": "event", - "params": [], - "kind": "type", - "definition": "@type event() :: String.t()" - }, - { - "line": 279, - "name": "topic", - "params": [], - "kind": "type", - "definition": "@type topic() :: String.t()" - } - ], - "Phoenix.CodeReloader.Server": [], - "Mix.Phoenix.Scope": [], - "Phoenix.Param.Atom": [], - "Phoenix.Param.Map": [], - "Phoenix.Transports.LongPoll.Server": [], - "Plug.Exception.Phoenix.ActionClauseError": [], - "Phoenix.NotAcceptableError": [], - "Mix.Tasks.Phx.Gen.Release": [], - "Phoenix.Endpoint.SyncCodeReloadPlug": [], - "Phoenix.Param.Any": [], - "Phoenix.Socket.Reply": [ - { - "line": 67, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Socket.Reply, join_ref: term(), payload: term(), ref: term(), status: term(), topic: term()}" - } - ], - "Phoenix.ChannelTest": [], - "Phoenix.Transports.LongPoll": [], - "Phoenix.Endpoint.Supervisor": [], - "Mix.Tasks.Phx.Gen.Secret": [], - "Phoenix.ChannelTest.NoopSerializer": [], - "Phoenix.Router": [], - "Phoenix.Presence": [ - { - "line": 209, - "name": "topic", - "params": [], - "kind": "type", - "definition": "@type topic() :: String.t()" - }, - { - "line": 208, - "name": "presence", - "params": [], - "kind": "type", - "definition": "@type presence() :: %{key: String.t(), meta: map()}" - }, - { - "line": 207, - "name": "presences", - "params": [], - "kind": "type", - "definition": "@type presences() :: %{String.t() => %{metas: [map()]}}" - } - ], - "Phoenix.Endpoint.RenderErrors": [], - "Mix.Phoenix.Schema": [], - "Phoenix.Debug": [], - "Phoenix.Socket.V2.JSONSerializer": [], - "Phoenix.MissingParamError": [], - "Inspect.Phoenix.Socket.Message": [], - "Phoenix.CodeReloader": [], - "Phoenix.Socket.InvalidMessageError": [], - "Phoenix.Socket.V1.JSONSerializer": [], - "Phoenix.Socket.Message": [ - { - "line": 16, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Socket.Message, event: term(), join_ref: term(), payload: term(), ref: term(), topic: term()}" - } - ], - "Phoenix.Controller.Pipeline": [], - "Mix.Tasks.Phx.Server": [], - "Mix.Tasks.Phx.Routes": [], - "Phoenix.ConnTest": [], - "Mix.Tasks.Phx.Gen.Live": [], - "Phoenix.Socket.Broadcast": [ - { - "line": 83, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Socket.Broadcast, event: term(), payload: term(), topic: term()}" - } - ], - "Phoenix.Router.MalformedURIError": [], - "Phoenix.Presence.Tracker": [], - "Phoenix.Transports.WebSocket": [], - "Phoenix.Router.ConsoleFormatter": [], - "Mix.Tasks.Compile.Phoenix": [], - "Phoenix.Socket.PoolSupervisor": [], - "Phoenix.Endpoint.Cowboy2Adapter": [], - "Phoenix.Config": [], - "Phoenix.Digester.Compressor": [], - "Phoenix.Digester": [], - "Phoenix.CodeReloader.MixListener": [], - "Phoenix.VerifiedRoutes": [ - { - "line": 275, - "name": "formatted_route", - "params": [], - "kind": "type", - "definition": "@type formatted_route() :: %{verb: String.t(), path: String.t(), label: String.t()}" - }, - { - "line": 274, - "name": "plug_opts", - "params": [], - "kind": "type", - "definition": "@type plug_opts() :: any()" - } - ], - "Mix.Tasks.Phx.Gen.Json": [], - "Phoenix.Param.BitString": [], - "Mix.Phoenix": [], - "Mix.Phoenix.Context": [], - "Mix.Tasks.Phx.Gen.Context": [], - "Phoenix.Token": [ - { - "line": 113, - "name": "signed_at_opt", - "params": [], - "kind": "type", - "definition": "@type signed_at_opt() :: {:signed_at, pos_integer()}" - }, - { - "line": 112, - "name": "max_age_opt", - "params": [], - "kind": "type", - "definition": "@type max_age_opt() :: {:max_age, pos_integer() | :infinity}" - }, - { - "line": 107, - "name": "shared_opt", - "params": [], - "kind": "type", - "definition": "@type shared_opt() :: {:key_iterations, pos_integer()} | {:key_length, pos_integer()} | {:key_digest, :sha256 | :sha384 | :sha512}" - }, - { - "line": 101, - "name": "context", - "params": [], - "kind": "type", - "definition": "@type context() :: Plug.Conn.t() | %{endpoint: atom(), optional(atom()) => any()} | atom() | binary()" - } - ], - "Phoenix.Router.Scope": [], - "Phoenix.Router.Route": [ - { - "line": 45, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Router.Route, assigns: term(), helper: term(), hosts: term(), kind: term(), line: term(), metadata: term(), path: term(), pipe_through: term(), plug: term(), plug_opts: term(), private: term(), trailing_slash?: term(), verb: term(), warn_on_verify?: term()}" - } - ], - "Mix.Tasks.Phx.Gen.Auth": [], - "Mix.Tasks.Phx.Gen.Auth.Injector": [ - { - "line": 7, - "name": "schema", - "params": [], - "kind": "type", - "definition": "@type schema() :: %{__struct__: Mix.Phoenix.Schema, alias: term(), api_route_prefix: term(), assocs: term(), attrs: term(), binary_id: term(), collection: term(), context_app: term(), defaults: term(), embedded?: term(), file: term(), fixture_params: term(), fixture_unique_functions: term(), generate?: term(), human_plural: term(), human_singular: term(), indexes: term(), migration?: term(), migration_defaults: term(), migration_module: term(), module: term(), optionals: term(), opts: term(), params: term(), plural: term(), prefix: term(), redacts: term(), repo: term(), repo_alias: term(), route_helper: term(), route_prefix: term(), sample_id: term(), scope: term(), singular: term(), string_attr: term(), table: term(), timestamp_type: term(), types: term(), uniques: term(), web_namespace: term(), web_path: term()}" - } - ], - "Mix.Tasks.Phx": [], - "Phoenix.Router.Resource": [ - { - "line": 25, - "name": "t", - "params": [], - "kind": "type", - "definition": "@type t() :: %{__struct__: Phoenix.Router.Resource, actions: term(), collection: term(), controller: term(), member: term(), param: term(), path: term(), route: term(), singleton: term()}" - } - ], - "Mix.Tasks.Phx.Gen.Cert": [], - "Mix.Tasks.Phx.Gen.Auth.Migration": [], - "Mix.Tasks.Phx.Gen.Presence": [], - "Mix.Tasks.Phx.Digest.Clean": [] - }, - "extraction_metadata": { - "modules_processed": 92, - "modules_with_debug_info": 92, - "modules_without_debug_info": 0, - "total_calls": 1513, - "total_functions": 1633, - "extraction_time_ms": 165, - "total_specs": 260, - "total_types": 27, - "total_structs": 19 - }, - "generated_at": "2025-12-09T22:19:05.291943Z" -} diff --git a/src/fixtures/mod.rs b/src/fixtures/mod.rs deleted file mode 100644 index c61a082..0000000 --- a/src/fixtures/mod.rs +++ /dev/null @@ -1,74 +0,0 @@ -//! Test fixtures for execute tests. -//! -//! This module provides JSON fixtures for testing commands. Fixtures are -//! loaded at compile time using `include_str!` for zero runtime overhead. -//! -//! ## Available Fixtures -//! -//! - [`CALL_GRAPH`] - Function locations and call relationships -//! - [`TYPE_SIGNATURES`] - Function type signatures -//! - [`STRUCTS`] - Struct definitions with fields -//! -//! ## Usage -//! -//! ```ignore -//! use crate::fixtures; -//! -//! crate::execute_test_fixture! { -//! fixture_name: populated_db, -//! json: fixtures::CALL_GRAPH, -//! project: "test_project", -//! } -//! ``` - -/// Call graph fixture with function locations and call relationships. -/// -/// Contains: -/// - 5 modules: Controller, Accounts, Service, Repo, Notifier -/// - 15 functions with various arities and kinds (def/defp) -/// - 11 call edges forming a realistic call graph -/// -/// Use for: trace, reverse_trace, calls_from, calls_to, path, hotspots, -/// unused, depends_on, depended_by -pub const CALL_GRAPH: &str = include_str!("call_graph.json"); - -/// Type signatures fixture with function specs. -/// -/// Contains: -/// - 3 modules: Accounts, Users, Repo -/// - 9 function signatures with typed arguments and return types -/// -/// Use for: search (functions kind), function -pub const TYPE_SIGNATURES: &str = include_str!("type_signatures.json"); - -/// Struct definitions fixture. -/// -/// Contains: -/// - 3 structs: User, Post, Comment -/// - Various field types with defaults and required flags -/// -/// Use for: struct command -pub const STRUCTS: &str = include_str!("structs.json"); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_call_graph_is_valid_json() { - let _: serde_json::Value = serde_json::from_str(CALL_GRAPH) - .expect("CALL_GRAPH should be valid JSON"); - } - - #[test] - fn test_type_signatures_is_valid_json() { - let _: serde_json::Value = serde_json::from_str(TYPE_SIGNATURES) - .expect("TYPE_SIGNATURES should be valid JSON"); - } - - #[test] - fn test_structs_is_valid_json() { - let _: serde_json::Value = serde_json::from_str(STRUCTS) - .expect("STRUCTS should be valid JSON"); - } -} diff --git a/src/fixtures/output/calls_from/empty.toon b/src/fixtures/output/calls_from/empty.toon deleted file mode 100644 index 17638e5..0000000 --- a/src/fixtures/output/calls_from/empty.toon +++ /dev/null @@ -1,4 +0,0 @@ -function_pattern: get_user -items[0]: -module_pattern: MyApp.Accounts -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/calls_from/single.json b/src/fixtures/output/calls_from/single.json deleted file mode 100644 index 624f34a..0000000 --- a/src/fixtures/output/calls_from/single.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "module_pattern": "MyApp.Accounts", - "function_pattern": "get_user", - "total_items": 1, - "items": [ - { - "name": "MyApp.Accounts", - "file": "lib/my_app/accounts.ex", - "entries": [ - { - "name": "get_user", - "arity": 1, - "kind": "", - "start_line": 10, - "end_line": 15, - "calls": [ - { - "caller": { - "module": "MyApp.Accounts", - "name": "get_user", - "arity": 1, - "kind": "", - "file": "lib/my_app/accounts.ex", - "start_line": 10, - "end_line": 15 - }, - "callee": { - "module": "MyApp.Repo", - "name": "get", - "arity": 2 - }, - "line": 12, - "call_type": "remote" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/calls_from/single.toon b/src/fixtures/output/calls_from/single.toon deleted file mode 100644 index 9700867..0000000 --- a/src/fixtures/output/calls_from/single.toon +++ /dev/null @@ -1,27 +0,0 @@ -function_pattern: get_user -items[1]: - - entries[1]: - - arity: 1 - calls[1]: - - call_type: remote - callee: - arity: 2 - module: MyApp.Repo - name: get - caller: - arity: 1 - end_line: 15 - file: lib/my_app/accounts.ex - kind: "" - module: MyApp.Accounts - name: get_user - start_line: 10 - line: 12 - end_line: 15 - kind: "" - name: get_user - start_line: 10 - file: lib/my_app/accounts.ex - name: MyApp.Accounts -module_pattern: MyApp.Accounts -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/calls_to/empty.toon b/src/fixtures/output/calls_to/empty.toon deleted file mode 100644 index 28bbe1a..0000000 --- a/src/fixtures/output/calls_to/empty.toon +++ /dev/null @@ -1,4 +0,0 @@ -function_pattern: get -items[0]: -module_pattern: MyApp.Repo -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/calls_to/single.json b/src/fixtures/output/calls_to/single.json deleted file mode 100644 index 4f0a32d..0000000 --- a/src/fixtures/output/calls_to/single.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "module_pattern": "MyApp.Repo", - "function_pattern": "get", - "total_items": 1, - "items": [ - { - "name": "MyApp.Repo", - "entries": [ - { - "name": "get", - "arity": 2, - "callers": [ - { - "caller": { - "module": "MyApp.Accounts", - "name": "get_user", - "arity": 1, - "kind": "", - "file": "lib/my_app/accounts.ex", - "start_line": 10, - "end_line": 15 - }, - "callee": { - "module": "MyApp.Repo", - "name": "get", - "arity": 2 - }, - "line": 12, - "call_type": "remote" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/calls_to/single.toon b/src/fixtures/output/calls_to/single.toon deleted file mode 100644 index faa89e8..0000000 --- a/src/fixtures/output/calls_to/single.toon +++ /dev/null @@ -1,23 +0,0 @@ -function_pattern: get -items[1]: - - entries[1]: - - arity: 2 - callers[1]: - - call_type: remote - callee: - arity: 2 - module: MyApp.Repo - name: get - caller: - arity: 1 - end_line: 15 - file: lib/my_app/accounts.ex - kind: "" - module: MyApp.Accounts - name: get_user - start_line: 10 - line: 12 - name: get - name: MyApp.Repo -module_pattern: MyApp.Repo -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/depended_by/empty.toon b/src/fixtures/output/depended_by/empty.toon deleted file mode 100644 index 79c4726..0000000 --- a/src/fixtures/output/depended_by/empty.toon +++ /dev/null @@ -1,3 +0,0 @@ -items[0]: -module_pattern: MyApp.Repo -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/depended_by/single.json b/src/fixtures/output/depended_by/single.json deleted file mode 100644 index d019661..0000000 --- a/src/fixtures/output/depended_by/single.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "module_pattern": "MyApp.Repo", - "total_items": 1, - "items": [ - { - "name": "MyApp.Service", - "entries": [ - { - "function": "fetch", - "arity": 1, - "kind": "def", - "start_line": 10, - "end_line": 20, - "file": "lib/service.ex", - "targets": [ - { - "function": "get", - "arity": 2, - "line": 15 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/depended_by/single.toon b/src/fixtures/output/depended_by/single.toon deleted file mode 100644 index 7c5689b..0000000 --- a/src/fixtures/output/depended_by/single.toon +++ /dev/null @@ -1,13 +0,0 @@ -items[1]: - - entries[1]: - - arity: 1 - end_line: 20 - file: lib/service.ex - function: fetch - kind: def - start_line: 10 - targets[1]{arity,function,line}: - 2,get,15 - name: MyApp.Service -module_pattern: MyApp.Repo -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/depends_on/empty.toon b/src/fixtures/output/depends_on/empty.toon deleted file mode 100644 index 69400de..0000000 --- a/src/fixtures/output/depends_on/empty.toon +++ /dev/null @@ -1,3 +0,0 @@ -items[0]: -module_pattern: MyApp.Controller -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/depends_on/single.json b/src/fixtures/output/depends_on/single.json deleted file mode 100644 index 7fea175..0000000 --- a/src/fixtures/output/depends_on/single.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "module_pattern": "MyApp.Controller", - "total_items": 1, - "items": [ - { - "name": "MyApp.Service", - "entries": [ - { - "name": "process", - "arity": 1, - "callers": [ - { - "caller": { - "module": "MyApp.Controller", - "name": "index", - "arity": 1, - "kind": "def", - "file": "lib/controller.ex", - "start_line": 5, - "end_line": 12 - }, - "callee": { - "module": "MyApp.Service", - "name": "process", - "arity": 1 - }, - "line": 7 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/depends_on/single.toon b/src/fixtures/output/depends_on/single.toon deleted file mode 100644 index 9f2bbbb..0000000 --- a/src/fixtures/output/depends_on/single.toon +++ /dev/null @@ -1,21 +0,0 @@ -items[1]: - - entries[1]: - - arity: 1 - callers[1]: - - callee: - arity: 1 - module: MyApp.Service - name: process - caller: - arity: 1 - end_line: 12 - file: lib/controller.ex - kind: def - module: MyApp.Controller - name: index - start_line: 5 - line: 7 - name: process - name: MyApp.Service -module_pattern: MyApp.Controller -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/function/empty.toon b/src/fixtures/output/function/empty.toon deleted file mode 100644 index 17638e5..0000000 --- a/src/fixtures/output/function/empty.toon +++ /dev/null @@ -1,4 +0,0 @@ -function_pattern: get_user -items[0]: -module_pattern: MyApp.Accounts -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/function/single.json b/src/fixtures/output/function/single.json deleted file mode 100644 index 4098463..0000000 --- a/src/fixtures/output/function/single.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "module_pattern": "MyApp.Accounts", - "function_pattern": "get_user", - "total_items": 1, - "items": [ - { - "name": "MyApp.Accounts", - "entries": [ - { - "name": "get_user", - "arity": 1, - "args": "integer()", - "return_type": "User.t() | nil" - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/function/single.toon b/src/fixtures/output/function/single.toon deleted file mode 100644 index 4bdacfa..0000000 --- a/src/fixtures/output/function/single.toon +++ /dev/null @@ -1,7 +0,0 @@ -function_pattern: get_user -items[1]: - - entries[1]{args,arity,name,return_type}: - integer(),1,get_user,User.t() | nil - name: MyApp.Accounts -module_pattern: MyApp.Accounts -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/hotspots/empty.toon b/src/fixtures/output/hotspots/empty.toon deleted file mode 100644 index c0f122d..0000000 --- a/src/fixtures/output/hotspots/empty.toon +++ /dev/null @@ -1,4 +0,0 @@ -items[0]: -kind_filter: total -module_pattern: * -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/hotspots/single.json b/src/fixtures/output/hotspots/single.json deleted file mode 100644 index 479fd44..0000000 --- a/src/fixtures/output/hotspots/single.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "module_pattern": "*", - "kind_filter": "total", - "total_items": 1, - "items": [ - { - "name": "MyApp.Accounts", - "entries": [ - { - "function": "get_user", - "incoming": 3, - "outgoing": 1, - "total": 4, - "ratio": 3.0 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/hotspots/single.toon b/src/fixtures/output/hotspots/single.toon deleted file mode 100644 index d354591..0000000 --- a/src/fixtures/output/hotspots/single.toon +++ /dev/null @@ -1,7 +0,0 @@ -items[1]: - - entries[1]{function,incoming,outgoing,ratio,total}: - get_user,3,1,3,4 - name: MyApp.Accounts -kind_filter: total -module_pattern: * -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/output/import/full.json b/src/fixtures/output/import/full.json deleted file mode 100644 index 9b19eb0..0000000 --- a/src/fixtures/output/import/full.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "schemas": { - "created": [ - "modules", - "functions" - ], - "already_existed": [ - "calls" - ] - }, - "cleared": true, - "modules_imported": 10, - "functions_imported": 50, - "calls_imported": 100, - "structs_imported": 5, - "function_locations_imported": 45, - "specs_imported": 25, - "types_imported": 12 -} \ No newline at end of file diff --git a/src/fixtures/output/import/full.toon b/src/fixtures/output/import/full.toon deleted file mode 100644 index 987381d..0000000 --- a/src/fixtures/output/import/full.toon +++ /dev/null @@ -1,11 +0,0 @@ -calls_imported: 100 -cleared: true -function_locations_imported: 45 -functions_imported: 50 -modules_imported: 10 -schemas: - already_existed[1]: calls - created[2]: modules,functions -specs_imported: 25 -structs_imported: 5 -types_imported: 12 \ No newline at end of file diff --git a/src/fixtures/output/location/empty.toon b/src/fixtures/output/location/empty.toon deleted file mode 100644 index 1b13069..0000000 --- a/src/fixtures/output/location/empty.toon +++ /dev/null @@ -1,4 +0,0 @@ -function_pattern: foo -module_pattern: MyApp -modules[0]: -total_clauses: 0 \ No newline at end of file diff --git a/src/fixtures/output/location/single.json b/src/fixtures/output/location/single.json deleted file mode 100644 index 8a73ecb..0000000 --- a/src/fixtures/output/location/single.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "module_pattern": "MyApp.Accounts", - "function_pattern": "get_user", - "total_clauses": 1, - "modules": [ - { - "name": "MyApp.Accounts", - "functions": [ - { - "name": "get_user", - "arity": 1, - "kind": "def", - "file": "lib/my_app/accounts.ex", - "clauses": [ - { - "line": 10, - "start_line": 10, - "end_line": 15 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/location/single.toon b/src/fixtures/output/location/single.toon deleted file mode 100644 index dba5f82..0000000 --- a/src/fixtures/output/location/single.toon +++ /dev/null @@ -1,12 +0,0 @@ -function_pattern: get_user -module_pattern: MyApp.Accounts -modules[1]: - - functions[1]: - - arity: 1 - clauses[1]{end_line,line,start_line}: - 15,10,10 - file: lib/my_app/accounts.ex - kind: def - name: get_user - name: MyApp.Accounts -total_clauses: 1 \ No newline at end of file diff --git a/src/fixtures/output/path/empty.toon b/src/fixtures/output/path/empty.toon deleted file mode 100644 index c311e6c..0000000 --- a/src/fixtures/output/path/empty.toon +++ /dev/null @@ -1,6 +0,0 @@ -from_function: index -from_module: MyApp.Controller -max_depth: 10 -paths[0]: -to_function: get -to_module: MyApp.Repo \ No newline at end of file diff --git a/src/fixtures/output/path/single.json b/src/fixtures/output/path/single.json deleted file mode 100644 index 188977d..0000000 --- a/src/fixtures/output/path/single.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "from_module": "MyApp.Controller", - "from_function": "index", - "to_module": "MyApp.Repo", - "to_function": "get", - "max_depth": 10, - "paths": [ - { - "steps": [ - { - "depth": 1, - "caller_module": "MyApp.Controller", - "caller_function": "index", - "callee_module": "MyApp.Service", - "callee_function": "fetch", - "callee_arity": 1, - "file": "lib/controller.ex", - "line": 7 - }, - { - "depth": 2, - "caller_module": "MyApp.Service", - "caller_function": "fetch", - "callee_module": "MyApp.Repo", - "callee_function": "get", - "callee_arity": 2, - "file": "lib/service.ex", - "line": 15 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/path/single.toon b/src/fixtures/output/path/single.toon deleted file mode 100644 index 55f3c95..0000000 --- a/src/fixtures/output/path/single.toon +++ /dev/null @@ -1,9 +0,0 @@ -from_function: index -from_module: MyApp.Controller -max_depth: 10 -paths[1]: - - steps[2]{callee_arity,callee_function,callee_module,caller_function,caller_module,depth,file,line}: - 1,fetch,MyApp.Service,index,MyApp.Controller,1,lib/controller.ex,7 - 2,get,MyApp.Repo,fetch,MyApp.Service,2,lib/service.ex,15 -to_function: get -to_module: MyApp.Repo \ No newline at end of file diff --git a/src/fixtures/output/reverse_trace/empty.toon b/src/fixtures/output/reverse_trace/empty.toon deleted file mode 100644 index 94178bb..0000000 --- a/src/fixtures/output/reverse_trace/empty.toon +++ /dev/null @@ -1,5 +0,0 @@ -max_depth: 5 -roots[0]: -target_function: get -target_module: MyApp.Repo -total_callers: 0 \ No newline at end of file diff --git a/src/fixtures/output/reverse_trace/single.json b/src/fixtures/output/reverse_trace/single.json deleted file mode 100644 index 5bff18d..0000000 --- a/src/fixtures/output/reverse_trace/single.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "target_module": "MyApp.Repo", - "target_function": "get", - "max_depth": 5, - "total_callers": 1, - "roots": [ - { - "module": "MyApp.Service", - "function": "fetch", - "arity": 1, - "kind": "def", - "start_line": 10, - "end_line": 20, - "file": "lib/service.ex", - "targets": [ - { - "module": "MyApp.Repo", - "function": "get", - "arity": 2, - "line": 15 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/reverse_trace/single.toon b/src/fixtures/output/reverse_trace/single.toon deleted file mode 100644 index e0244da..0000000 --- a/src/fixtures/output/reverse_trace/single.toon +++ /dev/null @@ -1,14 +0,0 @@ -max_depth: 5 -roots[1]: - - arity: 1 - end_line: 20 - file: lib/service.ex - function: fetch - kind: def - module: MyApp.Service - start_line: 10 - targets[1]{arity,function,line,module}: - 2,get,15,MyApp.Repo -target_function: get -target_module: MyApp.Repo -total_callers: 1 \ No newline at end of file diff --git a/src/fixtures/output/search/empty.toon b/src/fixtures/output/search/empty.toon deleted file mode 100644 index d112498..0000000 --- a/src/fixtures/output/search/empty.toon +++ /dev/null @@ -1,2 +0,0 @@ -kind: modules -pattern: test \ No newline at end of file diff --git a/src/fixtures/output/search/modules.json b/src/fixtures/output/search/modules.json deleted file mode 100644 index 6560dc4..0000000 --- a/src/fixtures/output/search/modules.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pattern": "MyApp", - "kind": "modules", - "modules": [ - { - "project": "default", - "name": "MyApp.Accounts", - "source": "unknown" - }, - { - "project": "default", - "name": "MyApp.Users", - "source": "unknown" - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/search/modules.toon b/src/fixtures/output/search/modules.toon deleted file mode 100644 index fb639a1..0000000 --- a/src/fixtures/output/search/modules.toon +++ /dev/null @@ -1,5 +0,0 @@ -kind: modules -modules[2]{name,project,source}: - MyApp.Accounts,default,unknown - MyApp.Users,default,unknown -pattern: MyApp \ No newline at end of file diff --git a/src/fixtures/output/trace/empty.toon b/src/fixtures/output/trace/empty.toon deleted file mode 100644 index 8f5c9e2..0000000 --- a/src/fixtures/output/trace/empty.toon +++ /dev/null @@ -1,5 +0,0 @@ -max_depth: 5 -roots[0]: -start_function: index -start_module: MyApp.Controller -total_calls: 0 \ No newline at end of file diff --git a/src/fixtures/output/trace/single.json b/src/fixtures/output/trace/single.json deleted file mode 100644 index 19c6861..0000000 --- a/src/fixtures/output/trace/single.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "start_module": "MyApp.Controller", - "start_function": "index", - "max_depth": 5, - "total_calls": 1, - "roots": [ - { - "module": "MyApp.Controller", - "function": "index", - "arity": 1, - "kind": "def", - "start_line": 5, - "end_line": 12, - "file": "lib/controller.ex", - "calls": [ - { - "module": "MyApp.Service", - "function": "fetch", - "arity": 1, - "line": 7 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/trace/single.toon b/src/fixtures/output/trace/single.toon deleted file mode 100644 index d66a2c2..0000000 --- a/src/fixtures/output/trace/single.toon +++ /dev/null @@ -1,14 +0,0 @@ -max_depth: 5 -roots[1]: - - arity: 1 - calls[1]{arity,function,line,module}: - 1,fetch,7,MyApp.Service - end_line: 12 - file: lib/controller.ex - function: index - kind: def - module: MyApp.Controller - start_line: 5 -start_function: index -start_module: MyApp.Controller -total_calls: 1 \ No newline at end of file diff --git a/src/fixtures/output/unused/empty.toon b/src/fixtures/output/unused/empty.toon deleted file mode 100644 index 4ae260a..0000000 --- a/src/fixtures/output/unused/empty.toon +++ /dev/null @@ -1,3 +0,0 @@ -items[0]: -module_pattern: * -total_items: 0 \ No newline at end of file diff --git a/src/fixtures/output/unused/single.json b/src/fixtures/output/unused/single.json deleted file mode 100644 index d0ee71e..0000000 --- a/src/fixtures/output/unused/single.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "module_pattern": "*", - "total_items": 1, - "items": [ - { - "name": "MyApp.Accounts", - "file": "lib/accounts.ex", - "entries": [ - { - "name": "unused_helper", - "arity": 0, - "kind": "defp", - "line": 35 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/fixtures/output/unused/single.toon b/src/fixtures/output/unused/single.toon deleted file mode 100644 index ac5cf7d..0000000 --- a/src/fixtures/output/unused/single.toon +++ /dev/null @@ -1,7 +0,0 @@ -items[1]: - - entries[1]{arity,kind,line,name}: - 0,defp,35,unused_helper - file: lib/accounts.ex - name: MyApp.Accounts -module_pattern: * -total_items: 1 \ No newline at end of file diff --git a/src/fixtures/structs.json b/src/fixtures/structs.json deleted file mode 100644 index a272afe..0000000 --- a/src/fixtures/structs.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "structs": { - "MyApp.User": { - "fields": [ - {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, - {"default": "nil", "field": "name", "required": true, "inferred_type": "String.t()"}, - {"default": "nil", "field": "email", "required": true, "inferred_type": "String.t()"}, - {"default": "false", "field": "admin", "required": false, "inferred_type": "boolean()"}, - {"default": "nil", "field": "inserted_at", "required": false, "inferred_type": "DateTime.t()"} - ] - }, - "MyApp.Post": { - "fields": [ - {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, - {"default": "nil", "field": "title", "required": true, "inferred_type": "String.t()"}, - {"default": "nil", "field": "body", "required": false, "inferred_type": "String.t()"}, - {"default": "nil", "field": "user_id", "required": true, "inferred_type": "integer()"}, - {"default": ":draft", "field": "status", "required": false, "inferred_type": "atom()"} - ] - }, - "MyApp.Comment": { - "fields": [ - {"default": "nil", "field": "id", "required": true, "inferred_type": "integer()"}, - {"default": "nil", "field": "content", "required": true, "inferred_type": "String.t()"}, - {"default": "nil", "field": "post_id", "required": true, "inferred_type": "integer()"}, - {"default": "nil", "field": "user_id", "required": true, "inferred_type": "integer()"} - ] - } - }, - "function_locations": {}, - "calls": [], - "type_signatures": {} -} diff --git a/src/fixtures/type_signatures.json b/src/fixtures/type_signatures.json deleted file mode 100644 index 86dd0db..0000000 --- a/src/fixtures/type_signatures.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "structs": {}, - "function_locations": {}, - "calls": [], - "type_signatures": {}, - "specs": { - "MyApp.Accounts": [ - { - "arity": 1, - "name": "get_user", - "line": 10, - "kind": "spec", - "clauses": [ - { - "full": "@spec get_user(integer()) :: User.t() | nil", - "input_strings": [ - "integer()" - ], - "return_strings": [ - "User.t()", - "nil" - ] - } - ] - }, - { - "arity": 2, - "name": "get_user", - "line": 15, - "kind": "spec", - "clauses": [ - { - "full": "@spec get_user(integer(), keyword()) :: User.t() | nil", - "input_strings": [ - "integer()", - "keyword()" - ], - "return_strings": [ - "User.t()", - "nil" - ] - } - ] - }, - { - "arity": 0, - "name": "list_users", - "line": 20, - "kind": "spec", - "clauses": [ - { - "full": "@spec list_users() :: [User.t()]", - "input_strings": [], - "return_strings": [ - "[User.t()]" - ] - } - ] - }, - { - "arity": 1, - "name": "create_user", - "line": 25, - "kind": "spec", - "clauses": [ - { - "full": "@spec create_user(map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}", - "input_strings": [ - "map()" - ], - "return_strings": [ - "{:ok, User.t()}", - "{:error, Ecto.Changeset.t()}" - ] - } - ] - } - ], - "MyApp.Users": [ - { - "arity": 1, - "name": "get_by_email", - "line": 10, - "kind": "spec", - "clauses": [ - { - "full": "@spec get_by_email(String.t()) :: User.t() | nil", - "input_strings": [ - "String.t()" - ], - "return_strings": [ - "User.t()", - "nil" - ] - } - ] - }, - { - "arity": 2, - "name": "authenticate", - "line": 15, - "kind": "spec", - "clauses": [ - { - "full": "@spec authenticate(String.t(), String.t()) :: {:ok, User.t()} | {:error, atom()}", - "input_strings": [ - "String.t()", - "String.t()" - ], - "return_strings": [ - "{:ok, User.t()}", - "{:error, atom()}" - ] - } - ] - } - ], - "MyApp.Repo": [ - { - "arity": 2, - "name": "get", - "line": 10, - "kind": "spec", - "clauses": [ - { - "full": "@spec get(module(), integer()) :: struct() | nil", - "input_strings": [ - "module()", - "integer()" - ], - "return_strings": [ - "struct()", - "nil" - ] - } - ] - }, - { - "arity": 1, - "name": "all", - "line": 15, - "kind": "spec", - "clauses": [ - { - "full": "@spec all(Ecto.Queryable.t()) :: [struct()]", - "input_strings": [ - "Ecto.Queryable.t()" - ], - "return_strings": [ - "[struct()]" - ] - } - ] - }, - { - "arity": 2, - "name": "insert", - "line": 20, - "kind": "spec", - "clauses": [ - { - "full": "@spec insert(struct(), keyword()) :: {:ok, struct()} | {:error, Ecto.Changeset.t()}", - "input_strings": [ - "struct()", - "keyword()" - ], - "return_strings": [ - "{:ok, struct()}", - "{:error, Ecto.Changeset.t()}" - ] - } - ] - } - ] - } -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 63a857c..0000000 --- a/src/main.rs +++ /dev/null @@ -1,33 +0,0 @@ -use clap::Parser; - -mod cli; -mod commands; -mod db; -mod dedup; -pub mod output; -mod queries; -pub mod types; -mod utils; -#[macro_use] -mod test_macros; -#[cfg(test)] -pub mod fixtures; -#[cfg(test)] -pub mod test_utils; -use cli::Args; -use commands::CommandRunner; - -fn main() -> Result<(), Box> { - let args = Args::parse(); - let db_path = cli::resolve_db_path(args.db); - - // Create .code_search directory if using default path - if db_path == std::path::PathBuf::from(".code_search/cozo.sqlite") { - std::fs::create_dir_all(".code_search").ok(); - } - - let db = db::open_db(&db_path)?; - let output = args.command.run(&db, args.format)?; - println!("{}", output); - Ok(()) -} diff --git a/src/output.rs b/src/output.rs deleted file mode 100644 index c52beb6..0000000 --- a/src/output.rs +++ /dev/null @@ -1,186 +0,0 @@ -//! Output formatting for command results. -//! -//! Supports multiple output formats: table (human-readable), JSON, and toon. - -use clap::ValueEnum; -use serde::Serialize; -use crate::types::{ModuleGroupResult, ModuleCollectionResult}; - -/// Output format for command results -#[derive(Debug, Clone, Copy, Default, ValueEnum)] -pub enum OutputFormat { - /// Human-readable table format - #[default] - Table, - /// JSON format - Json, - /// Token-efficient toon format - Toon, -} - -/// Trait for types that can be formatted for output -pub trait Outputable: Serialize { - /// Format as a human-readable table - fn to_table(&self) -> String; - - /// Format according to the specified output format - fn format(&self, format: OutputFormat) -> String { - match format { - OutputFormat::Table => self.to_table(), - OutputFormat::Json => serde_json::to_string_pretty(self).unwrap_or_default(), - OutputFormat::Toon => { - let json_value = serde_json::to_value(self).unwrap_or_default(); - toon::encode(&json_value, None) - } - } - } -} - -/// Trait for customizing table formatting for module-grouped results -/// -/// Provides hooks for formatting headers, empty states, summaries, and individual entries. -/// Used as a foundation for generating default `to_table()` implementations for generic -/// result types like `ModuleGroupResult` and `ModuleCollectionResult`. -pub trait TableFormatter { - type Entry; - - /// Format the header line(s) of the table - fn format_header(&self) -> String; - - /// Format the message shown when there are no results - fn format_empty_message(&self) -> String; - - /// Format the summary line after header and before entries - /// - /// # Arguments - /// * `total` - Total number of entries across all modules - /// * `module_count` - Number of modules in the result - fn format_summary(&self, total: usize, module_count: usize) -> String; - - /// Format the header for a module - /// - /// # Arguments - /// * `module_name` - Name of the module - /// * `module_file` - File path associated with the module (may be empty) - fn format_module_header(&self, module_name: &str, module_file: &str) -> String; - - /// Format the header for a module with access to its entries for aggregation - /// - /// Default implementation delegates to `format_module_header`. - /// Override this to include aggregated data from entries in the module header. - /// - /// # Arguments - /// * `module_name` - Name of the module - /// * `module_file` - File path associated with the module (may be empty) - /// * `entries` - Reference to the entries in this module - fn format_module_header_with_entries( - &self, - module_name: &str, - module_file: &str, - entries: &[Self::Entry], - ) -> String { - let _ = entries; // Silence unused warning for default implementation - self.format_module_header(module_name, module_file) - } - - /// Format a single entry within a module - /// - /// # Arguments - /// * `entry` - The entry to format - /// * `module_name` - Name of the parent module (for context) - /// * `module_file` - File path of the parent module (for context) - fn format_entry(&self, entry: &Self::Entry, module_name: &str, module_file: &str) -> String; - - /// Format optional detail lines for an entry - /// - /// Default implementation returns empty vec. Override to add details like calls/callers. - fn format_entry_details( - &self, - _entry: &Self::Entry, - _module_name: &str, - _module_file: &str, - ) -> Vec { - Vec::new() - } - - /// Whether to add a blank line after the summary - fn blank_after_summary(&self) -> bool { - true - } - - /// Whether to add a blank line before each module header - fn blank_before_module(&self) -> bool { - false - } -} - -/// Format module-grouped results as a table. -/// -/// This is the shared implementation for both ModuleGroupResult and ModuleCollectionResult. -/// Extracts the common logic to avoid duplication between the two impl blocks. -fn format_module_table(formatter: &F, items: &[crate::types::ModuleGroup], total_items: usize) -> String -where - F: TableFormatter, -{ - let mut lines = Vec::new(); - - lines.push(formatter.format_header()); - lines.push(String::new()); - - if items.is_empty() { - lines.push(formatter.format_empty_message()); - return lines.join("\n"); - } - - lines.push(formatter.format_summary(total_items, items.len())); - if formatter.blank_after_summary() { - lines.push(String::new()); - } - - for module in items { - if formatter.blank_before_module() { - lines.push(String::new()); - } - - lines.push(formatter.format_module_header_with_entries( - &module.name, - &module.file, - &module.entries, - )); - - for entry in &module.entries { - lines.push(format!( - " {}", - formatter.format_entry(entry, &module.name, &module.file) - )); - - for detail in formatter.format_entry_details(entry, &module.name, &module.file) { - lines.push(format!(" {}", detail)); - } - } - } - - lines.join("\n") -} - -/// Default implementation of Outputable for ModuleGroupResult using TableFormatter -impl Outputable for ModuleGroupResult -where - E: Serialize, - ModuleGroupResult: TableFormatter, -{ - fn to_table(&self) -> String { - format_module_table(self, &self.items, self.total_items) - } -} - -/// Default implementation of Outputable for ModuleCollectionResult using TableFormatter -impl Outputable for ModuleCollectionResult -where - E: Serialize, - ModuleCollectionResult: TableFormatter, -{ - fn to_table(&self) -> String { - format_module_table(self, &self.items, self.total_items) - } -} diff --git a/src/queries/accepts.rs b/src/queries/accepts.rs deleted file mode 100644 index 4ffcf01..0000000 --- a/src/queries/accepts.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum AcceptsError { - #[error("Accepts query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function with its input type specification -#[derive(Debug, Clone, Serialize)] -pub struct AcceptsEntry { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub inputs_string: String, - pub return_string: String, - pub line: i64, -} - -pub fn find_accepts( - db: &cozo::DbInstance, - pattern: &str, - project: &str, - use_regex: bool, - module_pattern: Option<&str>, - limit: u32, -) -> Result, Box> { - // Build inputs string filter - let match_fn = if use_regex { - "regex_matches(inputs_string, $pattern)" - } else { - "str_includes(inputs_string, $pattern)" - }; - - // Build module filter - let module_filter = match module_pattern { - Some(_) if use_regex => "regex_matches(module, $module_pattern)", - Some(_) => "str_includes(module, $module_pattern)", - None => "true", - }; - - let script = format!( - r#" - ?[project, module, name, arity, inputs_string, return_string, line] := - *specs{{project, module, name, arity, inputs_string, return_string, line}}, - project == $project, - {match_fn}, - {module_filter} - - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("pattern".to_string(), DataValue::Str(pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - if let Some(mod_pat) = module_pattern { - params.insert( - "module_pattern".to_string(), - DataValue::Str(mod_pat.into()), - ); - } - - let rows = run_query(db, &script, params).map_err(|e| AcceptsError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 7 { - let Some(project) = extract_string(&row[0]) else { - continue; - }; - let Some(module) = extract_string(&row[1]) else { - continue; - }; - let Some(name) = extract_string(&row[2]) else { - continue; - }; - let arity = extract_i64(&row[3], 0); - let inputs_string = extract_string(&row[4]).unwrap_or_default(); - let return_string = extract_string(&row[5]).unwrap_or_default(); - let line = extract_i64(&row[6], 0); - - results.push(AcceptsEntry { - project, - module, - name, - arity, - inputs_string, - return_string, - line, - }); - } - } - - Ok(results) -} diff --git a/src/queries/calls.rs b/src/queries/calls.rs deleted file mode 100644 index 0d42eec..0000000 --- a/src/queries/calls.rs +++ /dev/null @@ -1,131 +0,0 @@ -//! Unified call graph queries for finding function calls. -//! -//! This module provides a single query function that can find calls in either direction: -//! - `From`: Find all calls made BY the matched functions (outgoing calls) -//! - `To`: Find all calls made TO the matched functions (incoming calls) - -use std::error::Error; - -use cozo::DataValue; -use thiserror::Error; - -use crate::db::{extract_call_from_row, run_query, CallRowLayout, Params}; -use crate::types::Call; - -#[derive(Error, Debug)] -pub enum CallsError { - #[error("Calls query failed: {message}")] - QueryFailed { message: String }, -} - -/// Direction of call graph traversal -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CallDirection { - /// Find calls FROM the matched functions (what does this function call?) - From, - /// Find calls TO the matched functions (who calls this function?) - To, -} - -impl CallDirection { - /// Returns the field names to filter on based on direction - fn filter_fields(&self) -> (&'static str, &'static str, &'static str) { - match self { - CallDirection::From => ("caller_module", "caller_name", "caller_arity"), - CallDirection::To => ("callee_module", "callee_function", "callee_arity"), - } - } - - /// Returns the ORDER BY clause based on direction - fn order_clause(&self) -> &'static str { - match self { - CallDirection::From => { - "caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity" - } - CallDirection::To => { - "callee_module, callee_function, callee_arity, caller_module, caller_name, caller_arity" - } - } - } -} - -/// Find calls in the specified direction. -/// -/// - `From`: Returns all calls made by functions matching the pattern -/// - `To`: Returns all calls to functions matching the pattern -pub fn find_calls( - db: &cozo::DbInstance, - direction: CallDirection, - module_pattern: &str, - function_pattern: Option<&str>, - arity: Option, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - let (module_field, function_field, arity_field) = direction.filter_fields(); - let order_clause = direction.order_clause(); - - // Build conditions using the appropriate field names - let module_cond = - crate::utils::ConditionBuilder::new(module_field, "module_pattern").build(use_regex); - let function_cond = - crate::utils::OptionalConditionBuilder::new(function_field, "function_pattern") - .with_leading_comma() - .with_regex() - .build_with_regex(function_pattern.is_some(), use_regex); - let arity_cond = crate::utils::OptionalConditionBuilder::new(arity_field, "arity") - .with_leading_comma() - .build(arity.is_some()); - - let project_cond = ", project == $project"; - - // Join calls with function_locations to get caller's arity and line range - // Filter out struct calls (callee_function == '%') - let script = format!( - r#" - ?[project, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line, call_type] := - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line, call_type, caller_kind}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, start_line: caller_start_line, end_line: caller_end_line}}, - starts_with(caller_function, caller_name), - call_line >= caller_start_line, - call_line <= caller_end_line, - callee_function != '%', - {module_cond} - {function_cond} - {arity_cond} - {project_cond} - :order {order_clause} - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert( - "module_pattern".to_string(), - DataValue::Str(module_pattern.into()), - ); - if let Some(fn_pat) = function_pattern { - params.insert( - "function_pattern".to_string(), - DataValue::Str(fn_pat.into()), - ); - } - if let Some(a) = arity { - params.insert("arity".to_string(), DataValue::from(a)); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| CallsError::QueryFailed { - message: e.to_string(), - })?; - - let layout = CallRowLayout::from_headers(&rows.headers)?; - let results = rows - .rows - .iter() - .filter_map(|row| extract_call_from_row(row, &layout)) - .collect(); - - Ok(results) -} diff --git a/src/queries/calls_from.rs b/src/queries/calls_from.rs deleted file mode 100644 index 3248b95..0000000 --- a/src/queries/calls_from.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Find outgoing calls from functions. -//! -//! This is a convenience wrapper around [`super::calls::find_calls`] with -//! [`CallDirection::From`](super::calls::CallDirection::From). - -use std::error::Error; - -use super::calls::{find_calls, CallDirection}; -use crate::types::Call; - -pub fn find_calls_from( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: Option<&str>, - arity: Option, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - find_calls( - db, - CallDirection::From, - module_pattern, - function_pattern, - arity, - project, - use_regex, - limit, - ) -} diff --git a/src/queries/calls_to.rs b/src/queries/calls_to.rs deleted file mode 100644 index fef5d98..0000000 --- a/src/queries/calls_to.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Find incoming calls to functions. -//! -//! This is a convenience wrapper around [`super::calls::find_calls`] with -//! [`CallDirection::To`](super::calls::CallDirection::To). - -use std::error::Error; - -use super::calls::{find_calls, CallDirection}; -use crate::types::Call; - -pub fn find_calls_to( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: Option<&str>, - arity: Option, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - find_calls( - db, - CallDirection::To, - module_pattern, - function_pattern, - arity, - project, - use_regex, - limit, - ) -} diff --git a/src/queries/clusters.rs b/src/queries/clusters.rs deleted file mode 100644 index 892503c..0000000 --- a/src/queries/clusters.rs +++ /dev/null @@ -1,58 +0,0 @@ -//! Query to get all module calls for cluster analysis. -//! -//! Returns calls between different modules (no self-calls). -//! Clusters are computed in Rust by grouping modules by namespace. - -use std::error::Error; - -use cozo::DataValue; - -use crate::db::{run_query, Params}; - -/// Represents a call between two different modules -#[derive(Debug, Clone)] -pub struct ModuleCall { - pub caller_module: String, - pub callee_module: String, -} - -/// Get all inter-module calls (calls between different modules) -/// -/// Returns calls where caller_module != callee_module. -/// These are used to compute internal vs external connectivity per namespace cluster. -pub fn get_module_calls(db: &cozo::DbInstance, project: &str) -> Result, Box> { - let script = r#" - ?[caller_module, callee_module] := - *calls{project, caller_module, callee_module}, - project == $project, - caller_module != callee_module - "#; - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, script, params)?; - - let caller_idx = rows.headers.iter().position(|h| h == "caller_module") - .ok_or("Missing caller_module column")?; - let callee_idx = rows.headers.iter().position(|h| h == "callee_module") - .ok_or("Missing callee_module column")?; - - let results = rows - .rows - .iter() - .filter_map(|row| { - let caller = row.get(caller_idx).and_then(|v| v.get_str()); - let callee = row.get(callee_idx).and_then(|v| v.get_str()); - match (caller, callee) { - (Some(c), Some(m)) => Some(ModuleCall { - caller_module: c.to_string(), - callee_module: m.to_string(), - }), - _ => None, - } - }) - .collect(); - - Ok(results) -} diff --git a/src/queries/complexity.rs b/src/queries/complexity.rs deleted file mode 100644 index 672dd22..0000000 --- a/src/queries/complexity.rs +++ /dev/null @@ -1,112 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum ComplexityError { - #[error("Complexity query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function with complexity metrics -#[derive(Debug, Clone, Serialize)] -pub struct ComplexityMetric { - pub module: String, - pub name: String, - pub arity: i64, - pub line: i64, - pub complexity: i64, - pub max_nesting_depth: i64, - pub start_line: i64, - pub end_line: i64, - pub lines: i64, - pub generated_by: String, -} - -pub fn find_complexity_metrics( - db: &cozo::DbInstance, - min_complexity: i64, - min_depth: i64, - module_pattern: Option<&str>, - project: &str, - use_regex: bool, - exclude_generated: bool, - limit: u32, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build optional generated filter - let generated_filter = if exclude_generated { - ", generated_by == \"\"".to_string() - } else { - String::new() - }; - - let script = format!( - r#" - ?[module, name, arity, line, complexity, max_nesting_depth, start_line, end_line, lines, generated_by] := - *function_locations{{project, module, name, arity, line, complexity, max_nesting_depth, start_line, end_line, generated_by}}, - project == $project, - complexity >= $min_complexity, - max_nesting_depth >= $min_depth, - lines = end_line - start_line + 1 - {module_filter} - {generated_filter} - - :order -complexity, module, name - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert("min_complexity".to_string(), DataValue::from(min_complexity)); - params.insert("min_depth".to_string(), DataValue::from(min_depth)); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| ComplexityError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 10 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let arity = extract_i64(&row[2], 0); - let line = extract_i64(&row[3], 0); - let complexity = extract_i64(&row[4], 0); - let max_nesting_depth = extract_i64(&row[5], 0); - let start_line = extract_i64(&row[6], 0); - let end_line = extract_i64(&row[7], 0); - let lines = extract_i64(&row[8], 0); - let Some(generated_by) = extract_string(&row[9]) else { continue }; - - results.push(ComplexityMetric { - module, - name, - arity, - line, - complexity, - max_nesting_depth, - start_line, - end_line, - lines, - generated_by, - }); - } - } - - Ok(results) -} diff --git a/src/queries/cycles.rs b/src/queries/cycles.rs deleted file mode 100644 index 47a6105..0000000 --- a/src/queries/cycles.rs +++ /dev/null @@ -1,93 +0,0 @@ -//! Detect circular dependencies between modules using recursive queries. -//! -//! Uses CozoDB's recursive queries to: -//! 1. Build a deduplicated module dependency graph -//! 2. Find reachability (transitive closure) -//! 3. Detect modules that can reach themselves (cycles) -//! 4. Return cycle edges for reconstruction by the command - -use std::error::Error; - -use cozo::DataValue; - -use crate::db::{run_query, Params}; - -/// Edge in a cycle (from module -> to module) -#[derive(Debug, Clone)] -pub struct CycleEdge { - pub from: String, - pub to: String, -} - -/// Find all module pairs that form cycles -/// -/// Returns edges (from, to) where both modules are part of at least one cycle. -pub fn find_cycle_edges( - db: &cozo::DbInstance, - project: &str, - module_pattern: Option<&str>, -) -> Result, Box> { - // Build the recursive query for cycle detection - let script = r#" - # Build module dependency graph (deduplicated at module level) - module_deps[from, to] := - *calls{project, caller_module: from, callee_module: to}, - project == $project, - from != to - - # Find reachability (transitive closure) - what modules can be reached from each module - reaches[from, to] := module_deps[from, to] - reaches[from, to] := module_deps[from, mid], reaches[mid, to] - - # Find modules in cycles - modules that can reach themselves - in_cycle[module] := reaches[module, module] - - # Find cycle edges - direct edges between modules that are both in cycles - cycle_edge[from, to] := - module_deps[from, to], - in_cycle[from], - in_cycle[to] - - ?[from, to] := cycle_edge[from, to] - :order from, to - "#.to_string(); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params)?; - - // Parse results - let mut edges = Vec::new(); - - // Find column indices - let from_idx = rows - .headers - .iter() - .position(|h| h == "from") - .ok_or("Missing 'from' column")?; - let to_idx = rows - .headers - .iter() - .position(|h| h == "to") - .ok_or("Missing 'to' column")?; - - for row in &rows.rows { - if let (Some(DataValue::Str(from)), Some(DataValue::Str(to))) = - (row.get(from_idx), row.get(to_idx)) - { - // Apply module pattern filter if provided - if let Some(pattern) = module_pattern { - if !from.contains(pattern) && !to.contains(pattern) { - continue; - } - } - edges.push(CycleEdge { - from: from.to_string(), - to: to.to_string(), - }); - } - } - - Ok(edges) -} diff --git a/src/queries/depended_by.rs b/src/queries/depended_by.rs deleted file mode 100644 index d8a645b..0000000 --- a/src/queries/depended_by.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Find incoming module dependencies. -//! -//! This is a convenience wrapper around [`super::dependencies::find_dependencies`] with -//! [`DependencyDirection::Incoming`](super::dependencies::DependencyDirection::Incoming). - -use std::error::Error; - -use super::dependencies::{find_dependencies as query_dependencies, DependencyDirection}; -use crate::types::Call; - -pub fn find_dependents( - db: &cozo::DbInstance, - module_pattern: &str, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - query_dependencies( - db, - DependencyDirection::Incoming, - module_pattern, - project, - use_regex, - limit, - ) -} diff --git a/src/queries/dependencies.rs b/src/queries/dependencies.rs deleted file mode 100644 index 49225a0..0000000 --- a/src/queries/dependencies.rs +++ /dev/null @@ -1,113 +0,0 @@ -//! Unified module dependency queries. -//! -//! This module provides a single query function that can find dependencies in either direction: -//! - `Outgoing`: Find modules that the matched module depends ON (imports/calls into) -//! - `Incoming`: Find modules that depend on (are depended BY) the matched module - -use std::error::Error; - -use cozo::DataValue; -use thiserror::Error; - -use crate::db::{extract_call_from_row, run_query, CallRowLayout, Params}; -use crate::types::Call; - -#[derive(Error, Debug)] -pub enum DependencyError { - #[error("Dependency query failed: {message}")] - QueryFailed { message: String }, -} - -/// Direction of dependency analysis -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum DependencyDirection { - /// Find modules that the matched module depends ON (outgoing dependencies) - /// Query: "What does module X call?" - Outgoing, - /// Find modules that depend on the matched module (incoming dependencies) - /// Query: "Who calls module X?" - Incoming, -} - -impl DependencyDirection { - /// Returns the field name to filter on based on direction - fn filter_field(&self) -> &'static str { - match self { - DependencyDirection::Outgoing => "caller_module", - DependencyDirection::Incoming => "callee_module", - } - } - - /// Returns the ORDER BY clause based on direction - fn order_clause(&self) -> &'static str { - match self { - DependencyDirection::Outgoing => { - "callee_module, callee_function, callee_arity, caller_module, caller_name, caller_arity, call_line" - } - DependencyDirection::Incoming => { - "caller_module, caller_name, caller_arity, callee_function, callee_arity, call_line" - } - } - } -} - -/// Find module dependencies in the specified direction. -/// -/// - `Outgoing`: Returns calls from the matched module to other modules -/// - `Incoming`: Returns calls from other modules to the matched module -/// -/// Self-references (calls within the same module) are excluded. -pub fn find_dependencies( - db: &cozo::DbInstance, - direction: DependencyDirection, - module_pattern: &str, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - let filter_field = direction.filter_field(); - let order_clause = direction.order_clause(); - - // Build module condition using the appropriate field name - let module_cond = - crate::utils::ConditionBuilder::new(filter_field, "module_pattern").build(use_regex); - - // Query calls with function_locations join for caller metadata, excluding self-references - // Filter out struct calls (callee_function != '%') - let script = format!( - r#" - ?[caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, - starts_with(caller_function, caller_name), - call_line >= caller_start_line, - call_line <= caller_end_line, - callee_function != '%', - {module_cond}, - caller_module != callee_module, - project == $project - :order {order_clause} - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert( - "module_pattern".to_string(), - DataValue::Str(module_pattern.into()), - ); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| DependencyError::QueryFailed { - message: e.to_string(), - })?; - - let layout = CallRowLayout::from_headers(&rows.headers)?; - let results = rows - .rows - .iter() - .filter_map(|row| extract_call_from_row(row, &layout)) - .collect(); - - Ok(results) -} diff --git a/src/queries/depends_on.rs b/src/queries/depends_on.rs deleted file mode 100644 index 44edfbf..0000000 --- a/src/queries/depends_on.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Find outgoing module dependencies. -//! -//! This is a convenience wrapper around [`super::dependencies::find_dependencies`] with -//! [`DependencyDirection::Outgoing`](super::dependencies::DependencyDirection::Outgoing). - -use std::error::Error; - -use super::dependencies::{find_dependencies as query_dependencies, DependencyDirection}; -use crate::types::Call; - -pub fn find_dependencies( - db: &cozo::DbInstance, - module_pattern: &str, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - query_dependencies( - db, - DependencyDirection::Outgoing, - module_pattern, - project, - use_regex, - limit, - ) -} diff --git a/src/queries/duplicates.rs b/src/queries/duplicates.rs deleted file mode 100644 index 7d3adbd..0000000 --- a/src/queries/duplicates.rs +++ /dev/null @@ -1,106 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum DuplicatesError { - #[error("Duplicates query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function that has a duplicate implementation (same AST or source hash) -#[derive(Debug, Clone, Serialize)] -pub struct DuplicateFunction { - pub hash: String, - pub module: String, - pub name: String, - pub arity: i64, - pub line: i64, - pub file: String, -} - -pub fn find_duplicates( - db: &cozo::DbInstance, - project: &str, - module_pattern: Option<&str>, - use_regex: bool, - use_exact: bool, - exclude_generated: bool, -) -> Result, Box> { - // Choose hash field based on exact flag - let hash_field = if use_exact { "source_sha" } else { "ast_sha" }; - - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build optional generated filter - let generated_filter = if exclude_generated { - ", generated_by == \"\"".to_string() - } else { - String::new() - }; - - // Query to find duplicate hashes and their functions - let script = format!( - r#" - # Find hashes that appear more than once (count unique functions per hash) - hash_counts[{hash_field}, count(module)] := - *function_locations{{project, module, name, arity, {hash_field}, generated_by}}, - project == $project, - {hash_field} != "" - {generated_filter} - - # Get all functions with duplicate hashes - ?[{hash_field}, module, name, arity, line, file] := - *function_locations{{project, module, name, arity, line, file, {hash_field}, generated_by}}, - hash_counts[{hash_field}, cnt], - cnt > 1, - project == $project - {module_filter} - {generated_filter} - - :order {hash_field}, module, name, arity - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| DuplicatesError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(hash) = extract_string(&row[0]) else { continue }; - let Some(module) = extract_string(&row[1]) else { continue }; - let Some(name) = extract_string(&row[2]) else { continue }; - let arity = extract_i64(&row[3], 0); - let line = extract_i64(&row[4], 0); - let Some(file) = extract_string(&row[5]) else { continue }; - - results.push(DuplicateFunction { - hash, - module, - name, - arity, - line, - file, - }); - } - } - - Ok(results) -} diff --git a/src/queries/file.rs b/src/queries/file.rs deleted file mode 100644 index 30f7dff..0000000 --- a/src/queries/file.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum FileError { - #[error("File query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function defined in a file -#[derive(Debug, Clone, Serialize)] -pub struct FileFunctionDef { - pub module: String, - pub name: String, - pub arity: i64, - pub kind: String, - pub line: i64, - pub start_line: i64, - pub end_line: i64, - pub pattern: String, - pub guard: String, - #[serde(skip_serializing_if = "String::is_empty")] - pub file: String, -} - -/// Find all functions in modules matching a pattern -/// Returns a flat vec of functions with location info (for browse-module) -pub fn find_functions_in_module( - db: &cozo::DbInstance, - module_pattern: &str, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - // Build module filter - let module_filter = if use_regex { - "regex_matches(module, $module_pattern)" - } else { - "module == $module_pattern" - }; - - // Query to find all functions in matching modules - let script = format!( - r#" - ?[module, name, arity, kind, line, start_line, end_line, file, pattern, guard] := - *function_locations{{project, module, name, arity, line, file, kind, start_line, end_line, pattern, guard}}, - project == $project, - {module_filter} - - :order module, start_line, name, arity, line - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); - - let rows = run_query(db, &script, params).map_err(|e| FileError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - - for row in rows.rows { - if row.len() >= 10 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let arity = extract_i64(&row[2], 0); - let Some(kind) = extract_string(&row[3]) else { continue }; - let line = extract_i64(&row[4], 0); - let start_line = extract_i64(&row[5], 0); - let end_line = extract_i64(&row[6], 0); - let file = extract_string(&row[7]).unwrap_or_default(); - let pattern = extract_string(&row[8]).unwrap_or_default(); - let guard = extract_string(&row[9]).unwrap_or_default(); - - results.push(FileFunctionDef { - module, - name, - arity, - kind, - line, - start_line, - end_line, - pattern, - guard, - file, - }); - } - } - - Ok(results) -} diff --git a/src/queries/function.rs b/src/queries/function.rs deleted file mode 100644 index 08dbc13..0000000 --- a/src/queries/function.rs +++ /dev/null @@ -1,92 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; - -#[derive(Error, Debug)] -pub enum FunctionError { - #[error("Function query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function signature -#[derive(Debug, Clone, Serialize)] -pub struct FunctionSignature { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub args: String, - pub return_type: String, -} - -pub fn find_functions( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: &str, - arity: Option, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - // Build query conditions using helpers - let module_cond = crate::utils::ConditionBuilder::new("module", "module_pattern").build(use_regex); - let function_cond = crate::utils::ConditionBuilder::new("name", "function_pattern") - .with_leading_comma() - .build(use_regex); - let arity_cond = crate::utils::OptionalConditionBuilder::new("arity", "arity") - .with_leading_comma() - .build(arity.is_some()); - let project_cond = ", project == $project"; - - let script = format!( - r#" - ?[project, module, name, arity, args, return_type] := - *functions{{project, module, name, arity, args, return_type}}, - {module_cond} - {function_cond} - {arity_cond} - {project_cond} - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); - params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); - if let Some(a) = arity { - params.insert("arity".to_string(), DataValue::from(a)); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| FunctionError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(project) = extract_string(&row[0]) else { continue }; - let Some(module) = extract_string(&row[1]) else { continue }; - let Some(name) = extract_string(&row[2]) else { continue }; - let arity = extract_i64(&row[3], 0); - let args = extract_string_or(&row[4], ""); - let return_type = extract_string_or(&row[5], ""); - - results.push(FunctionSignature { - project, - module, - name, - arity, - args, - return_type, - }); - } - } - - Ok(results) -} diff --git a/src/queries/hotspots.rs b/src/queries/hotspots.rs deleted file mode 100644 index 5f3a94c..0000000 --- a/src/queries/hotspots.rs +++ /dev/null @@ -1,292 +0,0 @@ -use std::error::Error; - -use clap::ValueEnum; -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_f64, extract_i64, extract_string, run_query, Params}; - -/// What type of hotspots to find -#[derive(Debug, Clone, Copy, Default, ValueEnum)] -pub enum HotspotKind { - /// Functions with most incoming calls (most called) - #[default] - Incoming, - /// Functions with most outgoing calls (calls many things) - Outgoing, - /// Functions with highest total (incoming + outgoing) - Total, - /// Functions with highest ratio of incoming to outgoing calls (boundary functions) - Ratio, -} - -#[derive(Error, Debug)] -pub enum HotspotsError { - #[error("Hotspots query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function hotspot with call counts -#[derive(Debug, Clone, Serialize)] -pub struct Hotspot { - pub module: String, - pub function: String, - pub incoming: i64, - pub outgoing: i64, - pub total: i64, - pub ratio: f64, -} - -/// Get lines of code per module (sum of function line counts) -pub fn get_module_loc( - db: &cozo::DbInstance, - project: &str, - module_pattern: Option<&str>, - use_regex: bool, -) -> Result, Box> { - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - let script = format!( - r#" - # Calculate lines per function and sum by module - module_loc[module, sum(lines)] := - *function_locations{{project, module, start_line, end_line}}, - project == $project, - lines = end_line - start_line + 1 - {module_filter} - - ?[module, loc] := - module_loc[module, loc] - - :order -loc - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { - message: e.to_string(), - })?; - - let mut loc_map = std::collections::HashMap::new(); - for row in rows.rows { - if row.len() >= 2 { - if let Some(module) = extract_string(&row[0]) { - let loc = extract_i64(&row[1], 0); - loc_map.insert(module, loc); - } - } - } - - Ok(loc_map) -} - -/// Get function count per module -pub fn get_function_counts( - db: &cozo::DbInstance, - project: &str, - module_pattern: Option<&str>, - use_regex: bool, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - let script = format!( - r#" - func_counts[module, count(name)] := - *function_locations{{project, module, name}}, - project == $project - {module_filter} - - ?[module, func_count] := - func_counts[module, func_count] - - :order -func_count - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { - message: e.to_string(), - })?; - - let mut counts = std::collections::HashMap::new(); - for row in rows.rows { - if row.len() >= 2 { - if let Some(module) = extract_string(&row[0]) { - let count = extract_i64(&row[1], 0); - counts.insert(module, count); - } - } - } - - Ok(counts) -} - -pub fn find_hotspots( - db: &cozo::DbInstance, - kind: HotspotKind, - module_pattern: Option<&str>, - project: &str, - use_regex: bool, - limit: u32, - exclude_generated: bool, - require_outgoing: bool, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build optional generated filter - let generated_filter = if exclude_generated { - ", generated_by == \"\"".to_string() - } else { - String::new() - }; - - // Build optional outgoing filter (for boundaries - exclude leaf nodes) - let outgoing_filter = if require_outgoing { - ", outgoing > 0".to_string() - } else { - String::new() - }; - - let order_by = match kind { - HotspotKind::Incoming => "incoming", - HotspotKind::Outgoing => "outgoing", - HotspotKind::Total => "total", - HotspotKind::Ratio => "ratio", - }; - - // Query to find hotspots by counting incoming and outgoing calls - // We need to combine: - // 1. Functions as callers (outgoing) - count unique callees - // 2. Functions as callees (incoming) - count unique callers - // Note: caller_function may have arity suffix (e.g., "format/1") while callee_function doesn't ("format") - // We use callee_function as canonical name and match callers via starts_with - // Excludes recursive calls and deduplicates via intermediate relations - let script = format!( - r#" - # Get canonical function names (callee_function format, no arity suffix) - # A function's canonical name is how it appears as a callee - # Join with function_locations to filter generated functions - canonical[module, function] := - *calls{{project, callee_module, callee_function}}, - *function_locations{{project, module: callee_module, name: callee_function, generated_by}}, - project == $project, - module = callee_module, - function = callee_function - {generated_filter} - - # Distinct outgoing calls: match caller to canonical name - # caller_function is either "name" or "name/N", canonical_name is "name" - # Match: caller equals canonical OR starts with "canonical/" - distinct_outgoing[caller_module, canonical_name, callee_module, callee_function] := - *calls{{project, caller_module, caller_function, callee_module, callee_function}}, - canonical[caller_module, canonical_name], - project == $project, - (caller_function == canonical_name or starts_with(caller_function, concat(canonical_name, "/"))) - - # Count unique outgoing calls per function - outgoing_counts[module, function, count(callee_function)] := - distinct_outgoing[module, function, callee_module, callee_function] - - # Distinct incoming calls - distinct_incoming[callee_module, callee_function, caller_module, caller_function] := - *calls{{project, caller_module, caller_function, callee_module, callee_function}}, - canonical[callee_module, callee_function], - project == $project - - # Count unique incoming calls per function - incoming_counts[module, function, count(caller_function)] := - distinct_incoming[module, function, caller_module, caller_function] - - # Final query - functions with both incoming and outgoing - # Ratio = incoming / outgoing (high ratio = many callers, few dependencies = boundary) - ?[module, function, incoming, outgoing, total, ratio] := - incoming_counts[module, function, incoming], - outgoing_counts[module, function, outgoing], - total = incoming + outgoing, - ratio = if(outgoing == 0, 9999.0, incoming / outgoing) - {module_filter} - {outgoing_filter} - - # Functions with only incoming (no outgoing) - leaf nodes - # Excluded when require_outgoing is set - ?[module, function, incoming, outgoing, total, ratio] := - incoming_counts[module, function, incoming], - not outgoing_counts[module, function, _], - outgoing = 0, - total = incoming, - ratio = 9999.0 - {module_filter} - {outgoing_filter} - - # Functions with only outgoing (no incoming) - ?[module, function, incoming, outgoing, total, ratio] := - outgoing_counts[module, function, outgoing], - not incoming_counts[module, function, _], - incoming = 0, - total = outgoing, - ratio = 0.0 - {module_filter} - - :order -{order_by}, module, function - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| HotspotsError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(function) = extract_string(&row[1]) else { continue }; - let incoming = extract_i64(&row[2], 0); - let outgoing = extract_i64(&row[3], 0); - let total = extract_i64(&row[4], 0); - let ratio = extract_f64(&row[5], 0.0); - - results.push(Hotspot { - module, - function, - incoming, - outgoing, - total, - ratio, - }); - } - } - - Ok(results) -} diff --git a/src/queries/import.rs b/src/queries/import.rs deleted file mode 100644 index b7147eb..0000000 --- a/src/queries/import.rs +++ /dev/null @@ -1,724 +0,0 @@ -use std::error::Error; - -use cozo::{DataValue, DbInstance}; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{escape_string, escape_string_single, run_query, run_query_no_params, Params}; -use crate::queries::import_models::CallGraph; -use crate::queries::schema; - -/// Chunk size for batch database imports -const IMPORT_CHUNK_SIZE: usize = 500; - -#[derive(Error, Debug)] -pub enum ImportError { - #[error("Failed to read call graph file '{path}': {message}")] - FileReadFailed { path: String, message: String }, - - #[error("Failed to parse call graph JSON: {message}")] - JsonParseFailed { message: String }, - - #[allow(dead_code)] - #[error("Schema creation failed for '{relation}': {message}")] - SchemaCreationFailed { relation: String, message: String }, - - #[error("Failed to clear data: {message}")] - ClearFailed { message: String }, - - #[error("Failed to import {data_type}: {message}")] - ImportFailed { data_type: String, message: String }, -} - -/// Result of the import command execution -#[derive(Debug, Default, Serialize)] -pub struct ImportResult { - pub schemas: SchemaResult, - pub cleared: bool, - pub modules_imported: usize, - pub functions_imported: usize, - pub calls_imported: usize, - pub structs_imported: usize, - pub function_locations_imported: usize, - pub specs_imported: usize, - pub types_imported: usize, -} - -/// Result of schema creation -#[derive(Debug, Default, Serialize)] -pub struct SchemaResult { - pub created: Vec, - pub already_existed: Vec, -} - -pub fn create_schema(db: &DbInstance) -> Result> { - let mut result = SchemaResult::default(); - - let schema_results = schema::create_schema(db)?; - - for schema_result in schema_results { - if schema_result.created { - result.created.push(schema_result.relation); - } else { - result.already_existed.push(schema_result.relation); - } - } - - Ok(result) -} - -pub fn clear_project_data(db: &DbInstance, project: &str) -> Result<(), Box> { - // Delete all data for this project from each table - // Using :rm with a query that selects rows matching the project - let tables = [ - ("modules", "project, name"), - ("functions", "project, module, name, arity"), - ("calls", "project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column"), - ("struct_fields", "project, module, field"), - ("function_locations", "project, module, name, arity, line"), - ("specs", "project, module, name, arity"), - ("types", "project, module, name"), - ]; - - for (table, keys) in tables { - let script = format!( - r#" - ?[{keys}] := *{table}{{project: $project, {keys}}} - :rm {table} {{{keys}}} - "#, - table = table, - keys = keys - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - - run_query(db, &script, params).map_err(|e| ImportError::ClearFailed { - message: format!("Failed to clear {}: {}", table, e), - })?; - } - - Ok(()) -} - -/// Import rows in chunks into a CozoDB table -fn import_rows( - db: &DbInstance, - rows: Vec, - columns: &str, - table_spec: &str, - data_type: &str, -) -> Result> { - if rows.is_empty() { - return Ok(0); - } - - for chunk in rows.chunks(IMPORT_CHUNK_SIZE) { - let script = format!( - r#" - ?[{columns}] <- [{rows}] - :put {table_spec} - "#, - columns = columns, - rows = chunk.join(", "), - table_spec = table_spec - ); - - run_query_no_params(db, &script).map_err(|e| ImportError::ImportFailed { - data_type: data_type.to_string(), - message: e.to_string(), - })?; - } - - Ok(rows.len()) -} - -pub fn import_modules( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - // Collect unique modules from all data sources - let mut modules = std::collections::HashSet::new(); - modules.extend(graph.specs.keys().cloned()); - modules.extend(graph.function_locations.keys().cloned()); - modules.extend(graph.structs.keys().cloned()); - modules.extend(graph.types.keys().cloned()); - - let rows: Vec = modules - .iter() - .map(|m| { - format!( - r#"["{}", "{}", "", "unknown"]"#, - escape_string(project), - escape_string(m), - ) - }) - .collect(); - - import_rows( - db, - rows, - "project, name, file, source", - "modules { project, name => file, source }", - "modules", - ) -} - -pub fn import_functions( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let mut rows = Vec::new(); - - // Import functions from specs data - for (module, specs) in &graph.specs { - for spec in specs { - // Use first clause only - let (return_type, args) = spec - .clauses - .first() - .map(|c| (c.return_strings.join(" | "), c.input_strings.join(", "))) - .unwrap_or_default(); - - rows.push(format!( - r#"["{}", "{}", "{}", {}, "{}", "{}", "unknown"]"#, - escaped_project, - escape_string(module), - escape_string(&spec.name), - spec.arity, - escape_string(&return_type), - escape_string(&args), - )); - } - } - - import_rows( - db, - rows, - "project, module, name, arity, return_type, args, source", - "functions { project, module, name, arity => return_type, args, source }", - "functions", - ) -} - -pub fn import_calls( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let rows: Vec = graph - .calls - .iter() - .map(|call| { - let caller_kind = call.caller.kind.as_deref().unwrap_or(""); - let callee_args = call.callee.args.as_deref().unwrap_or(""); - - format!( - r#"["{}", "{}", "{}", "{}", "{}", {}, "{}", {}, {}, "{}", "{}", '{}']"#, - escaped_project, - escape_string(&call.caller.module), - escape_string(call.caller.function.as_deref().unwrap_or("")), - escape_string(&call.callee.module), - escape_string(&call.callee.function), - call.callee.arity, - escape_string(&call.caller.file), - call.caller.line.unwrap_or(0), - call.caller.column.unwrap_or(0), - escape_string(&call.call_type), - escape_string(caller_kind), - escape_string_single(callee_args), - ) - }) - .collect(); - - import_rows( - db, - rows, - "project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column, call_type, caller_kind, callee_args", - "calls { project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line, column => call_type, caller_kind, callee_args }", - "calls", - ) -} - -pub fn import_structs( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let mut rows = Vec::new(); - - for (module, def) in &graph.structs { - for field in &def.fields { - let inferred_type = field.inferred_type.as_deref().unwrap_or(""); - rows.push(format!( - r#"["{}", "{}", '{}', '{}', {}, "{}"]"#, - escaped_project, - escape_string(module), - escape_string_single(&field.field), - escape_string_single(&field.default), - field.required, - escape_string(inferred_type) - )); - } - } - - import_rows( - db, - rows, - "project, module, field, default_value, required, inferred_type", - "struct_fields { project, module, field => default_value, required, inferred_type }", - "struct_fields", - ) -} - -pub fn import_function_locations( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let mut rows = Vec::new(); - - for (module, functions) in &graph.function_locations { - for (_func_key, loc) in functions { - // Use deserialized fields directly from the JSON - let name = &loc.name; - let arity = loc.arity; - let line = loc.line; - - let source_file_absolute = loc.source_file_absolute.as_deref().unwrap_or(""); - let pattern = loc.pattern.as_deref().unwrap_or(""); - let guard = loc.guard.as_deref().unwrap_or(""); - let source_sha = loc.source_sha.as_deref().unwrap_or(""); - let ast_sha = loc.ast_sha.as_deref().unwrap_or(""); - let generated_by = loc.generated_by.as_deref().unwrap_or(""); - let macro_source = loc.macro_source.as_deref().unwrap_or(""); - - rows.push(format!( - r#"["{}", "{}", "{}", {}, {}, "{}", "{}", {}, "{}", {}, {}, '{}', '{}', "{}", "{}", {}, {}, "{}", "{}"]"#, - escaped_project, - escape_string(module), - escape_string(&name), - arity, - line, - escape_string(loc.file.as_deref().unwrap_or("")), - escape_string(source_file_absolute), - loc.column.unwrap_or(0), - escape_string(&loc.kind), - loc.start_line, - loc.end_line, - escape_string_single(pattern), - escape_string_single(guard), - escape_string(source_sha), - escape_string(ast_sha), - loc.complexity, - loc.max_nesting_depth, - escape_string(generated_by), - escape_string(macro_source), - )); - } - } - - import_rows( - db, - rows, - "project, module, name, arity, line, file, source_file_absolute, column, kind, start_line, end_line, pattern, guard, source_sha, ast_sha, complexity, max_nesting_depth, generated_by, macro_source", - "function_locations { project, module, name, arity, line => file, source_file_absolute, column, kind, start_line, end_line, pattern, guard, source_sha, ast_sha, complexity, max_nesting_depth, generated_by, macro_source }", - "function_locations", - ) -} - -pub fn import_specs( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let mut rows = Vec::new(); - - for (module, specs) in &graph.specs { - for spec in specs { - // Use first clause only (as per ticket recommendation) - let (inputs_string, return_string, full) = spec - .clauses - .first() - .map(|c| { - ( - c.input_strings.join(", "), - c.return_strings.join(" | "), - c.full.clone(), - ) - }) - .unwrap_or_default(); - - rows.push(format!( - r#"["{}", "{}", "{}", {}, "{}", {}, "{}", "{}", "{}"]"#, - escaped_project, - escape_string(module), - escape_string(&spec.name), - spec.arity, - escape_string(&spec.kind), - spec.line, - escape_string(&inputs_string), - escape_string(&return_string), - escape_string(&full), - )); - } - } - - import_rows( - db, - rows, - "project, module, name, arity, kind, line, inputs_string, return_string, full", - "specs { project, module, name, arity => kind, line, inputs_string, return_string, full }", - "specs", - ) -} - -pub fn import_types( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let escaped_project = escape_string(project); - let mut rows = Vec::new(); - - for (module, types) in &graph.types { - for type_def in types { - let params = type_def.params.join(", "); - - rows.push(format!( - r#"["{}", "{}", "{}", "{}", "{}", {}, '{}']"#, - escaped_project, - escape_string(module), - escape_string(&type_def.name), - escape_string(&type_def.kind), - escape_string(¶ms), - type_def.line, - escape_string_single(&type_def.definition), - )); - } - } - - import_rows( - db, - rows, - "project, module, name, kind, params, line, definition", - "types { project, module, name => kind, params, line, definition }", - "types", - ) -} - -/// Import a parsed CallGraph into the database. -/// -/// Creates schemas and imports all data (modules, functions, calls, structs, locations). -/// This is the core import logic used by both the CLI command and test utilities. -pub fn import_graph( - db: &DbInstance, - project: &str, - graph: &CallGraph, -) -> Result> { - let mut result = ImportResult::default(); - - result.schemas = create_schema(db)?; - result.modules_imported = import_modules(db, project, graph)?; - result.functions_imported = import_functions(db, project, graph)?; - result.calls_imported = import_calls(db, project, graph)?; - result.structs_imported = import_structs(db, project, graph)?; - result.function_locations_imported = import_function_locations(db, project, graph)?; - result.specs_imported = import_specs(db, project, graph)?; - result.types_imported = import_types(db, project, graph)?; - - Ok(result) -} - -/// Import a JSON string directly into the database. -/// -/// Convenience wrapper for tests that parses JSON and calls `import_graph`. -#[cfg(test)] -pub fn import_json_str( - db: &DbInstance, - content: &str, - project: &str, -) -> Result> { - let graph: CallGraph = - serde_json::from_str(content).map_err(|e| ImportError::JsonParseFailed { - message: e.to_string(), - })?; - - import_graph(db, project, &graph) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::db::{extract_string, open_db}; - use tempfile::NamedTempFile; - - // Test deserialization with all new fields present - #[test] - fn test_function_location_deserialize_with_new_fields() { - let json = r#"{ - "name": "test_func", - "arity": 2, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15, - "complexity": 5, - "max_nesting_depth": 3, - "generated_by": "Ecto.Schema", - "macro_source": "ecto/schema.ex" - }"#; - - let result: crate::queries::import_models::FunctionLocation = - serde_json::from_str(json).expect("Deserialization should succeed"); - - assert_eq!(result.complexity, 5); - assert_eq!(result.max_nesting_depth, 3); - assert_eq!(result.generated_by, Some("Ecto.Schema".to_string())); - assert_eq!(result.macro_source, Some("ecto/schema.ex".to_string())); - } - - // Test deserialization without optional fields (backward compatibility) - #[test] - fn test_function_location_deserialize_without_new_fields() { - let json = r#"{ - "name": "test_func", - "arity": 2, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15 - }"#; - - let result: crate::queries::import_models::FunctionLocation = - serde_json::from_str(json).expect("Deserialization should succeed"); - - // Should use defaults - assert_eq!(result.complexity, 1); // default_complexity - assert_eq!(result.max_nesting_depth, 0); // default - assert_eq!(result.generated_by, None); // default - assert_eq!(result.macro_source, None); // default - } - - // Test deserialization with empty string values - #[test] - fn test_function_location_deserialize_empty_strings() { - let json = r#"{ - "name": "test_func", - "arity": 2, - "kind": "def", - "line": 10, - "start_line": 10, - "end_line": 15, - "complexity": 1, - "max_nesting_depth": 0, - "generated_by": "", - "macro_source": "" - }"#; - - let result: crate::queries::import_models::FunctionLocation = - serde_json::from_str(json).expect("Deserialization should succeed"); - - // Empty strings should deserialize to None or empty string - assert_eq!(result.complexity, 1); - assert_eq!(result.max_nesting_depth, 0); - // Empty strings should parse as Some("") not None - assert_eq!(result.generated_by, Some("".to_string())); - assert_eq!(result.macro_source, Some("".to_string())); - } - - // Test import and database storage of new fields - #[test] - fn test_import_function_locations_with_new_fields() { - let json = r#"{ - "structs": {}, - "function_locations": { - "MyApp.Accounts": { - "process_data/2:20": { - "name": "process_data", - "arity": 2, - "file": "lib/accounts.ex", - "column": 5, - "kind": "def", - "line": 20, - "start_line": 20, - "end_line": 35, - "pattern": null, - "guard": null, - "source_sha": "", - "ast_sha": "", - "complexity": 7, - "max_nesting_depth": 4, - "generated_by": "Phoenix.Endpoint", - "macro_source": "phoenix/endpoint.ex" - } - } - }, - "calls": [], - "specs": {}, - "types": {} - }"#; - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); - - // Verify import succeeded - assert_eq!(result.function_locations_imported, 1); - - // Verify modules were created (MyApp.Accounts is inferred from function_locations) - assert!(result.modules_imported > 0); - - // If we got here, the new fields were successfully serialized and stored in the database - // The fact that import_graph succeeded means: - // 1. JSON deserialization worked with the new fields - // 2. import_function_locations() successfully formatted and inserted rows with 4 new fields - // 3. CozoDB schema accepted the data - } - - // Test import of struct fields with string-quoted atom syntax - #[test] - fn test_import_struct_fields_with_string_quoted_atoms() { - let json = r#"{ - "structs": { - "MyApp.User": { - "fields": [ - { - "field": "name", - "default": "nil", - "required": false, - "inferred_type": "String.t()" - }, - { - "field": ":\"user.id\"", - "default": "nil", - "required": false, - "inferred_type": "integer()" - }, - { - "field": ":\"first-name\"", - "default": ":\"foo.bar\"", - "required": true, - "inferred_type": "String.t()" - } - ] - } - }, - "function_locations": {}, - "calls": [], - "specs": {}, - "types": {} - }"#; - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); - - // Verify import succeeded - assert_eq!(result.structs_imported, 3); - - // Query the database to see what was actually stored - let query = r#" - ?[field, default_value] := *struct_fields{ - project: "test_project", - module: "MyApp.User", - field, - default_value - } - "#; - let rows = run_query_no_params(&db, query).expect("Query should succeed"); - - // Extract field names and defaults - let mut fields: Vec<(String, String)> = rows.rows.iter() - .filter_map(|row| { - let field = extract_string(&row[0])?; - let default = extract_string(&row[1])?; - Some((field, default)) - }) - .collect(); - fields.sort(); - - // Verify the string-quoted atom syntax is preserved in both field names and defaults - assert_eq!(fields.len(), 3); - assert_eq!(fields[0].0, r#":"first-name""#); - assert_eq!(fields[0].1, r#":"foo.bar""#); - assert_eq!(fields[1].0, r#":"user.id""#); - assert_eq!(fields[1].1, "nil"); - assert_eq!(fields[2].0, "name"); - assert_eq!(fields[2].1, "nil"); - } - - // Test import of types with string-quoted atoms in definition - #[test] - fn test_import_types_with_string_quoted_atoms() { - let json = r#"{ - "structs": {}, - "function_locations": {}, - "calls": [], - "specs": {}, - "types": { - "MyModule": [ - { - "name": "status", - "kind": "type", - "params": [], - "line": 5, - "definition": "@type status() :: :pending | :active | :\"special.status\"" - }, - { - "name": "config", - "kind": "type", - "params": [], - "line": 10, - "definition": "@type config() :: %{:\"api.key\" => String.t()}" - } - ] - } - }"#; - - let db_file = NamedTempFile::new().expect("Failed to create temp db file"); - let db = open_db(db_file.path()).expect("Failed to open db"); - - let result = import_json_str(&db, json, "test_project").expect("Import should succeed"); - - // Verify import succeeded - assert_eq!(result.types_imported, 2); - - // Query the database to see what was actually stored - let query = r#" - ?[name, definition] := *types{ - project: "test_project", - module: "MyModule", - name, - definition - } - "#; - let rows = run_query_no_params(&db, query).expect("Query should succeed"); - - // Extract type definitions - let mut types: Vec<(String, String)> = rows.rows.iter() - .filter_map(|row| { - let name = extract_string(&row[0])?; - let definition = extract_string(&row[1])?; - Some((name, definition)) - }) - .collect(); - types.sort(); - - // Verify the string-quoted atom syntax is preserved in definitions - assert_eq!(types.len(), 2); - assert_eq!(types[0].0, "config"); - assert_eq!(types[0].1, r#"@type config() :: %{:"api.key" => String.t()}"#); - assert_eq!(types[1].0, "status"); - assert_eq!(types[1].1, r#"@type status() :: :pending | :active | :"special.status""#); - } -} diff --git a/src/queries/import_models.rs b/src/queries/import_models.rs deleted file mode 100644 index d500e06..0000000 --- a/src/queries/import_models.rs +++ /dev/null @@ -1,145 +0,0 @@ -//! JSON import structures for call graph data. -//! -//! These types are used to deserialize the JSON output from the Elixir -//! call graph extractor during the import process. - -use serde::Deserialize; -use std::collections::HashMap; - -#[derive(Debug, Deserialize)] -pub struct CallGraph { - pub structs: HashMap, - pub function_locations: HashMap>, - pub calls: Vec, - #[serde(default)] - pub specs: HashMap>, - #[serde(default)] - pub types: HashMap>, -} - -#[derive(Debug, Deserialize)] -pub struct StructDef { - pub fields: Vec, -} - -#[derive(Debug, Deserialize)] -pub struct StructField { - pub default: String, - pub field: String, - pub required: bool, - pub inferred_type: Option, -} - -/// Function location with clause-level detail. -/// -/// The new format stores each function clause as a separate entry keyed by `function/arity:line`. -/// Fields `name` and `arity` are deserialized directly from the JSON. -#[derive(Debug, Deserialize)] -pub struct FunctionLocation { - pub name: String, - pub arity: u32, - /// Relative file path (accepts either "file" or "source_file" from JSON) - #[serde(alias = "source_file")] - pub file: Option, - #[serde(rename = "source_file_absolute")] - pub source_file_absolute: Option, - pub column: Option, - pub kind: String, - pub line: u32, - pub start_line: u32, - pub end_line: u32, - pub pattern: Option, - pub guard: Option, - pub source_sha: Option, - pub ast_sha: Option, - #[serde(default = "default_complexity")] - pub complexity: u32, - #[serde(default)] - pub max_nesting_depth: u32, - #[serde(default)] - pub generated_by: Option, - #[serde(default)] - pub macro_source: Option, -} - -fn default_complexity() -> u32 { - 1 -} - -#[derive(Debug, Deserialize)] -pub struct Call { - pub caller: Caller, - pub callee: Callee, - #[serde(rename = "type")] - pub call_type: String, -} - -#[derive(Debug, Deserialize)] -pub struct Caller { - pub module: String, - pub function: Option, - pub file: String, - pub line: Option, - pub column: Option, - /// Function kind: "def", "defp", "defmacro", "defmacrop" - pub kind: Option, -} - -#[derive(Debug, Deserialize)] -pub struct Callee { - pub module: String, - pub function: String, - pub arity: u32, - /// Argument names (comma-separated in source) - pub args: Option, -} - -/// A @spec or @callback definition. -/// -/// Format from extracted_trace.json: -/// ```json -/// { -/// "arity": 1, -/// "line": 19, -/// "name": "function_name", -/// "kind": "spec", -/// "clauses": [{ "full": "...", "inputs_string": [...], "return_string": "..." }] -/// } -/// ``` -#[derive(Debug, Deserialize)] -pub struct Spec { - pub name: String, - pub arity: u32, - pub line: u32, - pub kind: String, - pub clauses: Vec, -} - -/// A single clause within a spec definition. -#[derive(Debug, Deserialize)] -pub struct SpecClause { - pub full: String, - pub input_strings: Vec, - pub return_strings: Vec, -} - -/// A @type, @typep, or @opaque definition. -/// -/// Format from extracted_trace.json: -/// ```json -/// { -/// "line": 341, -/// "name": "socket_ref", -/// "params": [], -/// "kind": "type", -/// "definition": "@type socket_ref() :: {Pid, module(), binary(), binary(), binary()}" -/// } -/// ``` -#[derive(Debug, Deserialize)] -pub struct TypeDef { - pub name: String, - pub kind: String, - pub line: u32, - pub params: Vec, - pub definition: String, -} diff --git a/src/queries/large_functions.rs b/src/queries/large_functions.rs deleted file mode 100644 index 3bb1715..0000000 --- a/src/queries/large_functions.rs +++ /dev/null @@ -1,103 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum LargeFunctionsError { - #[error("Large functions query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function with line count information -#[derive(Debug, Clone, Serialize)] -pub struct LargeFunction { - pub module: String, - pub name: String, - pub arity: i64, - pub start_line: i64, - pub end_line: i64, - pub lines: i64, - pub file: String, - pub generated_by: String, -} - -pub fn find_large_functions( - db: &cozo::DbInstance, - min_lines: i64, - module_pattern: Option<&str>, - project: &str, - use_regex: bool, - include_generated: bool, - limit: u32, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build optional generated filter - let generated_filter = if include_generated { - String::new() - } else { - ", generated_by == \"\"".to_string() - }; - - let script = format!( - r#" - ?[module, name, arity, start_line, end_line, lines, file, generated_by] := - *function_locations{{project, module, name, arity, line, start_line, end_line, file, generated_by}}, - project == $project, - lines = end_line - start_line + 1, - lines >= $min_lines - {module_filter} - {generated_filter} - - :order -lines, module, name - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert("min_lines".to_string(), DataValue::from(min_lines)); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| LargeFunctionsError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 8 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let arity = extract_i64(&row[2], 0); - let start_line = extract_i64(&row[3], 0); - let end_line = extract_i64(&row[4], 0); - let lines = extract_i64(&row[5], 0); - let Some(file) = extract_string(&row[6]) else { continue }; - let Some(generated_by) = extract_string(&row[7]) else { continue }; - - results.push(LargeFunction { - module, - name, - arity, - start_line, - end_line, - lines, - file, - generated_by, - }); - } - } - - Ok(results) -} diff --git a/src/queries/location.rs b/src/queries/location.rs deleted file mode 100644 index 16d3c08..0000000 --- a/src/queries/location.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::error::Error; - -use cozo::{DataValue, Num}; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; - -#[derive(Error, Debug)] -pub enum LocationError { - #[error("Location query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function location result -#[derive(Debug, Clone, Serialize)] -pub struct FunctionLocation { - pub project: String, - pub file: String, - pub line: i64, - pub start_line: i64, - pub end_line: i64, - pub module: String, - pub kind: String, - pub name: String, - pub arity: i64, - pub pattern: String, - pub guard: String, -} - -pub fn find_locations( - db: &cozo::DbInstance, - module_pattern: Option<&str>, - function_pattern: &str, - arity: Option, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - // Build the query based on whether we're using regex or exact match - let fn_cond = if use_regex { - "regex_matches(name, $function_pattern)".to_string() - } else { - "name == $function_pattern".to_string() - }; - - let module_cond = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", module == $module_pattern".to_string(), - None => String::new(), - }; - - let arity_cond = if arity.is_some() { - ", arity == $arity" - } else { - "" - }; - - let project_cond = ", project == $project"; - - let script = format!( - r#" - ?[project, file, line, start_line, end_line, module, kind, name, arity, pattern, guard] := - *function_locations{{project, module, name, arity, line, file, kind, start_line, end_line, pattern, guard}}, - {fn_cond} - {module_cond} - {arity_cond} - {project_cond} - :order module, name, arity, line - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); - if let Some(mod_pat) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(mod_pat.into())); - } - if let Some(a) = arity { - params.insert("arity".to_string(), DataValue::Num(Num::Int(a))); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| LocationError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 11 { - // Order matches query: project, file, line, start_line, end_line, module, kind, name, arity, pattern, guard - let Some(project) = extract_string(&row[0]) else { continue }; - let Some(file) = extract_string(&row[1]) else { continue }; - let line = extract_i64(&row[2], 0); - let start_line = extract_i64(&row[3], 0); - let end_line = extract_i64(&row[4], 0); - let Some(module) = extract_string(&row[5]) else { continue }; - let kind = extract_string_or(&row[6], ""); - let Some(name) = extract_string(&row[7]) else { continue }; - let arity = extract_i64(&row[8], 0); - let pattern = extract_string_or(&row[9], ""); - let guard = extract_string_or(&row[10], ""); - - results.push(FunctionLocation { - project, - file, - line, - start_line, - end_line, - module, - kind, - name, - arity, - pattern, - guard, - }); - } - } - - Ok(results) -} diff --git a/src/queries/many_clauses.rs b/src/queries/many_clauses.rs deleted file mode 100644 index 10408da..0000000 --- a/src/queries/many_clauses.rs +++ /dev/null @@ -1,105 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum ManyClausesError { - #[error("Many clauses query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function with clause count information -#[derive(Debug, Clone, Serialize)] -pub struct ManyClauses { - pub module: String, - pub name: String, - pub arity: i64, - pub clauses: i64, - pub first_line: i64, - pub last_line: i64, - pub file: String, - pub generated_by: String, -} - -pub fn find_many_clauses( - db: &cozo::DbInstance, - min_clauses: i64, - module_pattern: Option<&str>, - project: &str, - use_regex: bool, - include_generated: bool, - limit: u32, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build optional generated filter - let generated_filter = if include_generated { - String::new() - } else { - ", generated_by == \"\"".to_string() - }; - - let script = format!( - r#" - clause_counts[module, name, arity, count(line), min(start_line), max(end_line), file, generated_by] := - *function_locations{{project, module, name, arity, line, start_line, end_line, file, generated_by}}, - project == $project - {module_filter} - {generated_filter} - - ?[module, name, arity, clauses, first_line, last_line, file, generated_by] := - clause_counts[module, name, arity, clauses, first_line, last_line, file, generated_by], - clauses >= $min_clauses - - :order -clauses, module, name - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert("min_clauses".to_string(), DataValue::from(min_clauses)); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| ManyClausesError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 8 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let arity = extract_i64(&row[2], 0); - let clauses = extract_i64(&row[3], 0); - let first_line = extract_i64(&row[4], 0); - let last_line = extract_i64(&row[5], 0); - let Some(file) = extract_string(&row[6]) else { continue }; - let Some(generated_by) = extract_string(&row[7]) else { continue }; - - results.push(ManyClauses { - module, - name, - arity, - clauses, - first_line, - last_line, - file, - generated_by, - }); - } - } - - Ok(results) -} diff --git a/src/queries/mod.rs b/src/queries/mod.rs deleted file mode 100644 index 8b45fe1..0000000 --- a/src/queries/mod.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Database query modules for call graph analysis. -//! -//! Each module contains CozoScript queries and result parsing for a specific -//! command. Queries execute against a CozoDB instance and return typed results. -//! -//! # Query Categories -//! -//! ## Data Import -//! - [`import`] - Import JSON call graph data into database relations -//! -//! ## Basic Lookups -//! - [`location`] - Find function definition locations by name -//! - [`function`] - Get function signatures with type information -//! - [`search`] - Full-text search across functions, specs, and types -//! - [`file`] - List all functions defined in a module/file -//! -//! ## Call Graph Traversal -//! - [`calls_from`] - Find all functions called by a given function -//! - [`calls_to`] - Find all callers of a given function -//! - [`trace`] - Forward call trace to specified depth -//! - [`reverse_trace`] - Backward call trace (who calls this, recursively) -//! - [`path`] - Find call path between two functions -//! -//! ## Dependency Analysis -//! - [`depends_on`] - Modules that a given module depends on -//! - [`depended_by`] - Modules that depend on a given module -//! -//! ## Code Quality -//! - [`unused`] - Find functions that are never called -//! - [`hotspots`] - Find most-called functions (high fan-in) -//! -//! ## Type System -//! - [`specs`] - Query @spec and @callback definitions -//! - [`types`] - Query @type, @typep, and @opaque definitions -//! - [`structs`] - Query struct definitions with field info -//! -//! # Performance -//! -//! All queries are indexed by module/function names. Most lookups are O(log n) -//! with O(m) result iteration where m is result count. Trace queries may be -//! O(n * depth) in worst case for highly connected graphs. -//! -//! # Query Pattern -//! -//! Each query module exports a single `find_*` or `*_query` function that: -//! 1. Builds a CozoScript query string with interpolated parameters -//! 2. Executes via `db.run_script()` -//! 3. Extracts results into typed Rust structs -//! -//! Parameters are escaped using [`crate::db::escape_string`] to prevent injection. - -pub mod accepts; -pub mod calls; -pub mod calls_from; -pub mod calls_to; -pub mod clusters; -pub mod complexity; -pub mod cycles; -pub mod depended_by; -pub mod dependencies; -pub mod depends_on; -pub mod duplicates; -pub mod file; -pub mod function; -pub mod hotspots; -pub mod import; -pub mod import_models; -pub mod large_functions; -pub mod location; -pub mod many_clauses; -pub mod path; -pub mod returns; -pub mod reverse_trace; -pub mod schema; -pub mod search; -pub mod specs; -pub mod struct_usage; -pub mod structs; -pub mod trace; -pub mod types; -pub mod unused; \ No newline at end of file diff --git a/src/queries/path.rs b/src/queries/path.rs deleted file mode 100644 index 8ab479e..0000000 --- a/src/queries/path.rs +++ /dev/null @@ -1,244 +0,0 @@ -use std::collections::HashMap; -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum PathError { - #[error("Path query failed: {message}")] - QueryFailed { message: String }, -} - -/// A single step in a call path -#[derive(Debug, Clone, Serialize)] -pub struct PathStep { - pub depth: i64, - pub caller_module: String, - pub caller_function: String, - pub callee_module: String, - pub callee_function: String, - pub callee_arity: i64, - pub file: String, - pub line: i64, -} - -/// A complete path from source to target -#[derive(Debug, Clone, Serialize)] -pub struct CallPath { - pub steps: Vec, -} - -#[allow(clippy::too_many_arguments)] -pub fn find_paths( - db: &cozo::DbInstance, - from_module: &str, - from_function: &str, - from_arity: Option, - to_module: &str, - to_function: &str, - to_arity: Option, - project: &str, - max_depth: u32, - limit: u32, -) -> Result, Box> { - // Build conditions using the ConditionBuilder utilities - let from_arity_cond = crate::utils::OptionalConditionBuilder::new("caller_arity", "from_arity") - .when_none("true") - .build(from_arity.is_some()); - - let to_arity_cond = crate::utils::OptionalConditionBuilder::new("callee_arity", "to_arity") - .when_none("true") - .build(to_arity.is_some()); - - // Simpler approach: trace forward from source to find all reachable calls, - // then filter to paths that end at the target. - // Returns edges on valid paths (may include multiple paths if they exist). - // Joins with function_locations to get caller arity for filtering. - let script = format!( - r#" - # Base case: direct calls from the source function - # Join with function_locations to get caller arity - # Uses starts_with to handle both "func" and "func/2" formats in caller_function - trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity}}, - starts_with(caller_function, caller_name), - caller_module == $from_module, - starts_with(caller_function, $from_function), - {from_arity_cond}, - project == $project, - depth = 1 - - # Recursive case: continue from callees we've found - trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := - trace[prev_depth, _, _, prev_callee_module, prev_callee_function, _, _, _], - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line}}, - caller_module == prev_callee_module, - starts_with(caller_function, prev_callee_function), - prev_depth < {max_depth}, - depth = prev_depth + 1, - project == $project - - # Find the depth at which we reach the target - target_depth[d] := - trace[d, _, _, callee_module, callee_function, callee_arity, _, _], - callee_module == $to_module, - starts_with(callee_function, $to_function), - {to_arity_cond} - - # Only return edges at depths <= minimum target depth (edges on valid paths) - ?[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line] := - trace[depth, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line], - target_depth[min_d], - depth <= min_d - - :order depth, caller_module, caller_function, callee_module, callee_function - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("from_module".to_string(), DataValue::Str(from_module.into())); - params.insert("from_function".to_string(), DataValue::Str(from_function.into())); - params.insert("to_module".to_string(), DataValue::Str(to_module.into())); - params.insert("to_function".to_string(), DataValue::Str(to_function.into())); - if let Some(a) = from_arity { - params.insert("from_arity".to_string(), DataValue::from(a)); - } - if let Some(a) = to_arity { - params.insert("to_arity".to_string(), DataValue::from(a)); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| PathError::QueryFailed { - message: e.to_string(), - })?; - - // Parse all edges from the query result - let mut edges: Vec = Vec::new(); - - for row in rows.rows { - if row.len() >= 8 { - let depth = extract_i64(&row[0], 0); - let Some(caller_module) = extract_string(&row[1]) else { continue }; - let Some(caller_function) = extract_string(&row[2]) else { continue }; - let Some(callee_module) = extract_string(&row[3]) else { continue }; - let Some(callee_function) = extract_string(&row[4]) else { continue }; - let callee_arity = extract_i64(&row[5], 0); - let Some(file) = extract_string(&row[6]) else { continue }; - let line = extract_i64(&row[7], 0); - - edges.push(PathStep { - depth, - caller_module, - caller_function, - callee_module, - callee_function, - callee_arity, - file, - line, - }); - } - } - - if edges.is_empty() { - return Ok(vec![]); - } - - // Build adjacency list: (module, function) -> list of edges from that node - // Key is (caller_module, caller_function), value is list of edges - let mut adj: HashMap<(String, String), Vec<&PathStep>> = HashMap::new(); - for edge in &edges { - adj.entry((edge.caller_module.clone(), edge.caller_function.clone())) - .or_default() - .push(edge); - } - - // Find all paths using DFS from source to target - let mut all_paths: Vec = Vec::new(); - let mut current_path: Vec = Vec::new(); - - // Find starting edges (depth 1, from the source function) - let starting_edges: Vec<&PathStep> = edges.iter().filter(|e| e.depth == 1).collect(); - - for start_edge in starting_edges { - current_path.clear(); - dfs_find_paths( - start_edge, - to_module, - to_function, - to_arity, - &adj, - &mut current_path, - &mut all_paths, - limit as usize, - ); - } - - Ok(all_paths) -} - -/// DFS to find all paths from current edge to target -fn dfs_find_paths( - current_edge: &PathStep, - to_module: &str, - to_function: &str, - to_arity: Option, - adj: &HashMap<(String, String), Vec<&PathStep>>, - current_path: &mut Vec, - all_paths: &mut Vec, - limit: usize, -) { - // Add current edge to path - current_path.push(current_edge.clone()); - - // Check if we reached the target - let at_target = current_edge.callee_module == to_module - && current_edge.callee_function == to_function - && to_arity.map_or(true, |a| current_edge.callee_arity == a); - - if at_target { - // Found a complete path - all_paths.push(CallPath { - steps: current_path.clone(), - }); - } else if all_paths.len() < limit { - // Continue searching from the callee - // Find edges where caller matches our callee - // Note: caller_function has arity suffix, callee_function doesn't - // So we need to find edges where caller starts with our callee_function - for (key, next_edges) in adj.iter() { - if key.0 == current_edge.callee_module && key.1.starts_with(¤t_edge.callee_function) { - for next_edge in next_edges { - // Avoid cycles - check if we've already visited this exact edge - let already_visited = current_path.iter().any(|e| { - e.caller_module == next_edge.caller_module - && e.caller_function == next_edge.caller_function - && e.callee_module == next_edge.callee_module - && e.callee_function == next_edge.callee_function - }); - - if !already_visited && all_paths.len() < limit { - dfs_find_paths( - next_edge, - to_module, - to_function, - to_arity, - adj, - current_path, - all_paths, - limit, - ); - } - } - } - } - } - - // Backtrack - current_path.pop(); -} diff --git a/src/queries/returns.rs b/src/queries/returns.rs deleted file mode 100644 index e4248c7..0000000 --- a/src/queries/returns.rs +++ /dev/null @@ -1,104 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum ReturnsError { - #[error("Returns query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function with its return type specification -#[derive(Debug, Clone, Serialize)] -pub struct ReturnEntry { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub return_string: String, - pub line: i64, -} - -pub fn find_returns( - db: &cozo::DbInstance, - pattern: &str, - project: &str, - use_regex: bool, - module_pattern: Option<&str>, - limit: u32, -) -> Result, Box> { - // Build return string filter - let match_fn = if use_regex { - "regex_matches(return_string, $pattern)" - } else { - "str_includes(return_string, $pattern)" - }; - - // Build module filter - let module_filter = match module_pattern { - Some(_) if use_regex => "regex_matches(module, $module_pattern)", - Some(_) => "str_includes(module, $module_pattern)", - None => "true", - }; - - let script = format!( - r#" - ?[project, module, name, arity, return_string, line] := - *specs{{project, module, name, arity, return_string, line}}, - project == $project, - {match_fn}, - {module_filter} - - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("pattern".to_string(), DataValue::Str(pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - if let Some(mod_pat) = module_pattern { - params.insert( - "module_pattern".to_string(), - DataValue::Str(mod_pat.into()), - ); - } - - let rows = run_query(db, &script, params).map_err(|e| ReturnsError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(project) = extract_string(&row[0]) else { - continue; - }; - let Some(module) = extract_string(&row[1]) else { - continue; - }; - let Some(name) = extract_string(&row[2]) else { - continue; - }; - let arity = extract_i64(&row[3], 0); - let return_string = extract_string(&row[4]).unwrap_or_default(); - let line = extract_i64(&row[5], 0); - - results.push(ReturnEntry { - project, - module, - name, - arity, - return_string, - line, - }); - } - } - - Ok(results) -} diff --git a/src/queries/reverse_trace.rs b/src/queries/reverse_trace.rs deleted file mode 100644 index dfce44c..0000000 --- a/src/queries/reverse_trace.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; - -#[derive(Error, Debug)] -pub enum ReverseTraceError { - #[error("Reverse trace query failed: {message}")] - QueryFailed { message: String }, -} - -/// A single step in the reverse call chain -#[derive(Debug, Clone, Serialize)] -pub struct ReverseTraceStep { - pub depth: i64, - pub caller_module: String, - pub caller_function: String, - pub caller_arity: i64, - pub caller_kind: String, - pub caller_start_line: i64, - pub caller_end_line: i64, - pub callee_module: String, - pub callee_function: String, - pub callee_arity: i64, - pub file: String, - pub line: i64, -} - -pub fn reverse_trace_calls( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: &str, - arity: Option, - project: &str, - use_regex: bool, - max_depth: u32, - limit: u32, -) -> Result, Box> { - // Build the starting conditions for the recursive query using helpers - // For reverse trace, we match on the callee (target) - let module_cond = crate::utils::ConditionBuilder::new("callee_module", "module_pattern").build(use_regex); - let function_cond = crate::utils::ConditionBuilder::new("callee_function", "function_pattern").build(use_regex); - let arity_cond = crate::utils::OptionalConditionBuilder::new("callee_arity", "arity") - .when_none("true") - .build(arity.is_some()); - - // Recursive query to trace call chains backwards, joined with function_locations for caller metadata - // Base case: calls TO the target function - // Recursive case: calls TO the callers we've found - let script = format!( - r#" - # Base case: calls to the target function, joined with function_locations - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, - starts_with(caller_function, caller_name), - call_line >= caller_start_line, - call_line <= caller_end_line, - {module_cond}, - {function_cond}, - project == $project, - {arity_cond}, - depth = 1 - - # Recursive case: calls to the callers we've found - # Note: prev_caller_function has arity suffix (e.g., "foo/2") but callee_function doesn't (e.g., "foo") - # So we use starts_with to match prev_caller_function starting with callee_function - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - trace[prev_depth, prev_caller_module, prev_caller_name, prev_caller_arity, _, _, _, _, _, _, _, _], - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, - callee_module == prev_caller_module, - callee_function == prev_caller_name, - callee_arity == prev_caller_arity, - starts_with(caller_function, caller_name), - call_line >= caller_start_line, - call_line <= caller_end_line, - prev_depth < {max_depth}, - depth = prev_depth + 1, - project == $project - - ?[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] - - :order depth, caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); - params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); - if let Some(a) = arity { - params.insert("arity".to_string(), DataValue::from(a)); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| ReverseTraceError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 12 { - let depth = extract_i64(&row[0], 0); - let Some(caller_module) = extract_string(&row[1]) else { continue }; - let Some(caller_function) = extract_string(&row[2]) else { continue }; - let caller_arity = extract_i64(&row[3], 0); - let caller_kind = extract_string_or(&row[4], ""); - let caller_start_line = extract_i64(&row[5], 0); - let caller_end_line = extract_i64(&row[6], 0); - let Some(callee_module) = extract_string(&row[7]) else { continue }; - let Some(callee_function) = extract_string(&row[8]) else { continue }; - let callee_arity = extract_i64(&row[9], 0); - let Some(file) = extract_string(&row[10]) else { continue }; - let line = extract_i64(&row[11], 0); - - results.push(ReverseTraceStep { - depth, - caller_module, - caller_function, - caller_arity, - caller_kind, - caller_start_line, - caller_end_line, - callee_module, - callee_function, - callee_arity, - file, - line, - }); - } - } - - Ok(results) -} diff --git a/src/queries/schema.rs b/src/queries/schema.rs deleted file mode 100644 index 3324e60..0000000 --- a/src/queries/schema.rs +++ /dev/null @@ -1,180 +0,0 @@ -//! Database schema creation and management. -//! -//! This module provides shared schema utilities used by both the import -//! and setup commands. It defines the database schema for all relations -//! and provides functions to create, check, and drop them. - -use std::error::Error; -use cozo::DbInstance; -use crate::db::try_create_relation; - -// Schema definitions - -pub const SCHEMA_MODULES: &str = r#" -:create modules { - project: String, - name: String - => - file: String default "", - source: String default "unknown" -} -"#; - -pub const SCHEMA_FUNCTIONS: &str = r#" -:create functions { - project: String, - module: String, - name: String, - arity: Int - => - return_type: String default "", - args: String default "", - source: String default "unknown" -} -"#; - -pub const SCHEMA_CALLS: &str = r#" -:create calls { - project: String, - caller_module: String, - caller_function: String, - callee_module: String, - callee_function: String, - callee_arity: Int, - file: String, - line: Int, - column: Int - => - call_type: String default "remote", - caller_kind: String default "", - callee_args: String default "" -} -"#; - -pub const SCHEMA_STRUCT_FIELDS: &str = r#" -:create struct_fields { - project: String, - module: String, - field: String - => - default_value: String, - required: Bool, - inferred_type: String -} -"#; - -pub const SCHEMA_FUNCTION_LOCATIONS: &str = r#" -:create function_locations { - project: String, - module: String, - name: String, - arity: Int, - line: Int - => - file: String, - source_file_absolute: String default "", - column: Int, - kind: String, - start_line: Int, - end_line: Int, - pattern: String default "", - guard: String default "", - source_sha: String default "", - ast_sha: String default "", - complexity: Int default 1, - max_nesting_depth: Int default 0, - generated_by: String default "", - macro_source: String default "" -} -"#; - -pub const SCHEMA_SPECS: &str = r#" -:create specs { - project: String, - module: String, - name: String, - arity: Int - => - kind: String, - line: Int, - inputs_string: String default "", - return_string: String default "", - full: String default "" -} -"#; - -pub const SCHEMA_TYPES: &str = r#" -:create types { - project: String, - module: String, - name: String - => - kind: String, - params: String default "", - line: Int, - definition: String default "" -} -"#; - -/// Result of schema creation operation -#[derive(Debug, Clone)] -pub struct SchemaCreationResult { - pub relation: String, - pub created: bool, -} - -/// Create all database schemas. -/// -/// Returns a list of all relations with their creation status. -/// If a relation already exists, returns Ok with created=false for that relation. -pub fn create_schema(db: &DbInstance) -> Result, Box> { - let mut result = Vec::new(); - - let schemas = [ - ("modules", SCHEMA_MODULES), - ("functions", SCHEMA_FUNCTIONS), - ("calls", SCHEMA_CALLS), - ("struct_fields", SCHEMA_STRUCT_FIELDS), - ("function_locations", SCHEMA_FUNCTION_LOCATIONS), - ("specs", SCHEMA_SPECS), - ("types", SCHEMA_TYPES), - ]; - - for (name, script) in schemas { - let created = try_create_relation(db, script)?; - result.push(SchemaCreationResult { - relation: name.to_string(), - created, - }); - } - - Ok(result) -} - -/// Get list of all relation names managed by this schema -pub fn relation_names() -> Vec<&'static str> { - vec![ - "modules", - "functions", - "calls", - "struct_fields", - "function_locations", - "specs", - "types", - ] -} - -/// Get schema script for a specific relation by name -#[allow(dead_code)] -pub fn schema_for_relation(name: &str) -> Option<&'static str> { - match name { - "modules" => Some(SCHEMA_MODULES), - "functions" => Some(SCHEMA_FUNCTIONS), - "calls" => Some(SCHEMA_CALLS), - "struct_fields" => Some(SCHEMA_STRUCT_FIELDS), - "function_locations" => Some(SCHEMA_FUNCTION_LOCATIONS), - "specs" => Some(SCHEMA_SPECS), - "types" => Some(SCHEMA_TYPES), - _ => None, - } -} diff --git a/src/queries/search.rs b/src/queries/search.rs deleted file mode 100644 index 13f12e0..0000000 --- a/src/queries/search.rs +++ /dev/null @@ -1,117 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; - -#[derive(Error, Debug)] -pub enum SearchError { - #[error("Search failed: {message}")] - QueryFailed { message: String }, -} - -/// A module search result -#[derive(Debug, Clone, Serialize)] -pub struct ModuleResult { - pub project: String, - pub name: String, - pub source: String, -} - -/// A function search result -#[derive(Debug, Clone, Serialize)] -pub struct FunctionResult { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub return_type: String, -} - -pub fn search_modules( - db: &cozo::DbInstance, - pattern: &str, - project: &str, - limit: u32, - use_regex: bool, -) -> Result, Box> { - let match_fn = if use_regex { "regex_matches" } else { "str_includes" }; - let script = format!( - r#" - ?[project, name, source] := *modules{{project, name, source}}, - project = $project, - {match_fn}(name, $pattern) - :limit {limit} - :order name - "#, - ); - - let mut params = Params::new(); - params.insert("pattern".to_string(), DataValue::Str(pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| SearchError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 3 { - let Some(project) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let source = extract_string_or(&row[2], "unknown"); - results.push(ModuleResult { project, name, source }); - } - } - - Ok(results) -} - -pub fn search_functions( - db: &cozo::DbInstance, - pattern: &str, - project: &str, - limit: u32, - use_regex: bool, -) -> Result, Box> { - let match_fn = if use_regex { "regex_matches" } else { "str_includes" }; - let script = format!( - r#" - ?[project, module, name, arity, return_type] := *functions{{project, module, name, arity, return_type}}, - project = $project, - {match_fn}(name, $pattern) - :limit {limit} - :order module, name, arity - "#, - ); - - let mut params = Params::new(); - params.insert("pattern".to_string(), DataValue::Str(pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| SearchError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 5 { - let Some(project) = extract_string(&row[0]) else { continue }; - let Some(module) = extract_string(&row[1]) else { continue }; - let Some(name) = extract_string(&row[2]) else { continue }; - let arity = extract_i64(&row[3], 0); - let return_type = extract_string_or(&row[4], ""); - results.push(FunctionResult { - project, - module, - name, - arity, - return_type, - }); - } - } - - Ok(results) -} diff --git a/src/queries/specs.rs b/src/queries/specs.rs deleted file mode 100644 index fa64ee6..0000000 --- a/src/queries/specs.rs +++ /dev/null @@ -1,127 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum SpecsError { - #[error("Specs query failed: {message}")] - QueryFailed { message: String }, -} - -/// A spec or callback definition -#[derive(Debug, Clone, Serialize)] -pub struct SpecDef { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub kind: String, - pub line: i64, - pub inputs_string: String, - pub return_string: String, - pub full: String, -} - -pub fn find_specs( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: Option<&str>, - kind_filter: Option<&str>, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - // Build module filter - let module_filter = if use_regex { - "regex_matches(module, $module_pattern)" - } else { - "module == $module_pattern" - }; - - // Build function filter - let function_filter = match function_pattern { - Some(_) if use_regex => ", regex_matches(name, $function_pattern)", - Some(_) => ", str_includes(name, $function_pattern)", - None => "", - }; - - // Build kind filter - let kind_filter_sql = match kind_filter { - Some(_) => ", kind == $kind", - None => "", - }; - - let script = format!( - r#" - ?[project, module, name, arity, kind, line, inputs_string, return_string, full] := - *specs{{project, module, name, arity, kind, line, inputs_string, return_string, full}}, - project == $project, - {module_filter} - {function_filter} - {kind_filter_sql} - - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert( - "module_pattern".to_string(), - DataValue::Str(module_pattern.into()), - ); - - if let Some(func) = function_pattern { - params.insert("function_pattern".to_string(), DataValue::Str(func.into())); - } - - if let Some(kind) = kind_filter { - params.insert("kind".to_string(), DataValue::Str(kind.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| SpecsError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 9 { - let Some(project) = extract_string(&row[0]) else { - continue; - }; - let Some(module) = extract_string(&row[1]) else { - continue; - }; - let Some(name) = extract_string(&row[2]) else { - continue; - }; - let arity = extract_i64(&row[3], 0); - let Some(kind) = extract_string(&row[4]) else { - continue; - }; - let line = extract_i64(&row[5], 0); - let inputs_string = extract_string(&row[6]).unwrap_or_default(); - let return_string = extract_string(&row[7]).unwrap_or_default(); - let full = extract_string(&row[8]).unwrap_or_default(); - - results.push(SpecDef { - project, - module, - name, - arity, - kind, - line, - inputs_string, - return_string, - full, - }); - } - } - - Ok(results) -} diff --git a/src/queries/struct_usage.rs b/src/queries/struct_usage.rs deleted file mode 100644 index 07b2b8e..0000000 --- a/src/queries/struct_usage.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum StructUsageError { - #[error("Struct usage query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function that accepts or returns a specific type -#[derive(Debug, Clone, Serialize)] -pub struct StructUsageEntry { - pub project: String, - pub module: String, - pub name: String, - pub arity: i64, - pub inputs_string: String, - pub return_string: String, - pub line: i64, -} - -pub fn find_struct_usage( - db: &cozo::DbInstance, - pattern: &str, - project: &str, - use_regex: bool, - module_pattern: Option<&str>, - limit: u32, -) -> Result, Box> { - // Build pattern matching function for both inputs and return - let match_fn = if use_regex { - "regex_matches(inputs_string, $pattern) or regex_matches(return_string, $pattern)" - } else { - "str_includes(inputs_string, $pattern) or str_includes(return_string, $pattern)" - }; - - // Build module filter - let module_filter = match module_pattern { - Some(_) if use_regex => "regex_matches(module, $module_pattern)", - Some(_) => "str_includes(module, $module_pattern)", - None => "true", - }; - - let script = format!( - r#" - ?[project, module, name, arity, inputs_string, return_string, line] := - *specs{{project, module, name, arity, inputs_string, return_string, line}}, - project == $project, - {match_fn}, - {module_filter} - - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("pattern".to_string(), DataValue::Str(pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - if let Some(mod_pat) = module_pattern { - params.insert( - "module_pattern".to_string(), - DataValue::Str(mod_pat.into()), - ); - } - - let rows = run_query(db, &script, params).map_err(|e| StructUsageError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 7 { - let Some(project) = extract_string(&row[0]) else { - continue; - }; - let Some(module) = extract_string(&row[1]) else { - continue; - }; - let Some(name) = extract_string(&row[2]) else { - continue; - }; - let arity = extract_i64(&row[3], 0); - let inputs_string = extract_string(&row[4]).unwrap_or_default(); - let return_string = extract_string(&row[5]).unwrap_or_default(); - let line = extract_i64(&row[6], 0); - - results.push(StructUsageEntry { - project, - module, - name, - arity, - inputs_string, - return_string, - line, - }); - } - } - - Ok(results) -} diff --git a/src/queries/structs.rs b/src/queries/structs.rs deleted file mode 100644 index 10686a5..0000000 --- a/src/queries/structs.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_bool, extract_string, extract_string_or, run_query, Params}; - -#[derive(Error, Debug)] -pub enum StructError { - #[error("Struct query failed: {message}")] - QueryFailed { message: String }, -} - -/// A struct field definition -#[derive(Debug, Clone, Serialize)] -pub struct StructField { - pub project: String, - pub module: String, - pub field: String, - pub default_value: String, - pub required: bool, - pub inferred_type: String, -} - -/// A struct with all its fields grouped -#[derive(Debug, Clone, Serialize)] -pub struct StructDefinition { - pub project: String, - pub module: String, - pub fields: Vec, -} - -/// Field information within a struct -#[derive(Debug, Clone, Serialize)] -pub struct FieldInfo { - pub name: String, - pub default_value: String, - pub required: bool, - pub inferred_type: String, -} - -pub fn find_struct_fields( - db: &cozo::DbInstance, - module_pattern: &str, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - let module_cond = if use_regex { - "regex_matches(module, $module_pattern)".to_string() - } else { - "module == $module_pattern".to_string() - }; - - let project_cond = ", project == $project"; - - let script = format!( - r#" - ?[project, module, field, default_value, required, inferred_type] := - *struct_fields{{project, module, field, default_value, required, inferred_type}}, - {module_cond} - {project_cond} - :order module, field - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| StructError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(project) = extract_string(&row[0]) else { continue }; - let Some(module) = extract_string(&row[1]) else { continue }; - let Some(field) = extract_string(&row[2]) else { continue }; - let default_value = extract_string_or(&row[3], ""); - let required = extract_bool(&row[4], false); - let inferred_type = extract_string_or(&row[5], ""); - - results.push(StructField { - project, - module, - field, - default_value, - required, - inferred_type, - }); - } - } - - Ok(results) -} - -pub fn group_fields_into_structs(fields: Vec) -> Vec { - use std::collections::BTreeMap; - - let mut grouped: BTreeMap<(String, String), Vec> = BTreeMap::new(); - - for field in fields { - let key = (field.project.clone(), field.module.clone()); - grouped.entry(key).or_default().push(FieldInfo { - name: field.field, - default_value: field.default_value, - required: field.required, - inferred_type: field.inferred_type, - }); - } - - grouped - .into_iter() - .map(|((project, module), fields)| StructDefinition { - project, - module, - fields, - }) - .collect() -} diff --git a/src/queries/trace.rs b/src/queries/trace.rs deleted file mode 100644 index bbcb7d0..0000000 --- a/src/queries/trace.rs +++ /dev/null @@ -1,132 +0,0 @@ -use std::error::Error; -use std::rc::Rc; - -use cozo::DataValue; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, extract_string_or, run_query, Params}; -use crate::types::{Call, FunctionRef}; - -#[derive(Error, Debug)] -pub enum TraceError { - #[error("Trace query failed: {message}")] - QueryFailed { message: String }, -} - -pub fn trace_calls( - db: &cozo::DbInstance, - module_pattern: &str, - function_pattern: &str, - arity: Option, - project: &str, - use_regex: bool, - max_depth: u32, - limit: u32, -) -> Result, Box> { - // Build the starting conditions for the recursive query using helpers - let module_cond = crate::utils::ConditionBuilder::new("caller_module", "module_pattern").build(use_regex); - let function_cond = crate::utils::ConditionBuilder::new("caller_name", "function_pattern").build(use_regex); - let arity_cond = crate::utils::OptionalConditionBuilder::new("caller_arity", "arity") - .when_none("true") - .build(arity.is_some()); - - // Recursive query to trace call chains, joined with function_locations for caller metadata - // Base case: direct calls from the starting function - // Recursive case: calls from functions we've already found - // Filter out struct calls (callee_function != '%') - let script = format!( - r#" - # Base case: calls from the starting function, joined with function_locations - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, - starts_with(caller_function, caller_name), - call_line >= caller_start_line, - call_line <= caller_end_line, - callee_function != '%', - {module_cond}, - {function_cond}, - project == $project, - {arity_cond}, - depth = 1 - - # Recursive case: calls from callees we've found - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - trace[prev_depth, _, _, _, _, _, _, prev_callee_module, prev_callee_function, _, _, _], - *calls{{project, caller_module, caller_function, callee_module, callee_function, callee_arity, file, line: call_line}}, - *function_locations{{project, module: caller_module, name: caller_name, arity: caller_arity, kind: caller_kind, start_line: caller_start_line, end_line: caller_end_line}}, - caller_module == prev_callee_module, - starts_with(caller_function, caller_name), - starts_with(caller_function, prev_callee_function), - call_line >= caller_start_line, - call_line <= caller_end_line, - callee_function != '%', - prev_depth < {max_depth}, - depth = prev_depth + 1, - project == $project - - ?[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] := - trace[depth, caller_module, caller_name, caller_arity, caller_kind, caller_start_line, caller_end_line, callee_module, callee_function, callee_arity, file, call_line] - - :order depth, caller_module, caller_name, caller_arity, call_line, callee_module, callee_function, callee_arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("module_pattern".to_string(), DataValue::Str(module_pattern.into())); - params.insert("function_pattern".to_string(), DataValue::Str(function_pattern.into())); - if let Some(a) = arity { - params.insert("arity".to_string(), DataValue::from(a)); - } - params.insert("project".to_string(), DataValue::Str(project.into())); - - let rows = run_query(db, &script, params).map_err(|e| TraceError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 12 { - let depth = extract_i64(&row[0], 0); - let Some(caller_module) = extract_string(&row[1]) else { continue }; - let Some(caller_name) = extract_string(&row[2]) else { continue }; - let caller_arity = extract_i64(&row[3], 0); - let caller_kind = extract_string_or(&row[4], ""); - let caller_start_line = extract_i64(&row[5], 0); - let caller_end_line = extract_i64(&row[6], 0); - let Some(callee_module) = extract_string(&row[7]) else { continue }; - let Some(callee_name) = extract_string(&row[8]) else { continue }; - let callee_arity = extract_i64(&row[9], 0); - let Some(file) = extract_string(&row[10]) else { continue }; - let line = extract_i64(&row[11], 0); - - let caller = FunctionRef::with_definition( - Rc::from(caller_module.into_boxed_str()), - Rc::from(caller_name.into_boxed_str()), - caller_arity, - Rc::from(caller_kind.into_boxed_str()), - Rc::from(file.into_boxed_str()), - caller_start_line, - caller_end_line, - ); - - // Callee doesn't have definition info from this query - let callee = FunctionRef::new( - Rc::from(callee_module.into_boxed_str()), - Rc::from(callee_name.into_boxed_str()), - callee_arity, - ); - - results.push(Call { - caller, - callee, - line, - call_type: None, - depth: Some(depth), - }); - } - } - - Ok(results) -} diff --git a/src/queries/types.rs b/src/queries/types.rs deleted file mode 100644 index aa08274..0000000 --- a/src/queries/types.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum TypesError { - #[error("Types query failed: {message}")] - QueryFailed { message: String }, -} - -/// A type definition (@type, @typep, @opaque) -#[derive(Debug, Clone, Serialize)] -pub struct TypeInfo { - pub project: String, - pub module: String, - pub name: String, - pub kind: String, - pub params: String, - pub line: i64, - pub definition: String, -} - -pub fn find_types( - db: &cozo::DbInstance, - module_pattern: &str, - name_filter: Option<&str>, - kind_filter: Option<&str>, - project: &str, - use_regex: bool, - limit: u32, -) -> Result, Box> { - // Build module filter - let module_filter = if use_regex { - "regex_matches(module, $module_pattern)" - } else { - "module == $module_pattern" - }; - - // Build name filter - let name_filter_sql = match name_filter { - Some(_) if use_regex => ", regex_matches(name, $name_pattern)", - Some(_) => ", str_includes(name, $name_pattern)", - None => "", - }; - - // Build kind filter - let kind_filter_sql = match kind_filter { - Some(_) => ", kind == $kind", - None => "", - }; - - let script = format!( - r#" - ?[project, module, name, kind, params, line, definition] := - *types{{project, module, name, kind, params, line, definition}}, - project == $project, - {module_filter} - {name_filter_sql} - {kind_filter_sql} - - :order module, name - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - params.insert( - "module_pattern".to_string(), - DataValue::Str(module_pattern.into()), - ); - - if let Some(name) = name_filter { - params.insert("name_pattern".to_string(), DataValue::Str(name.into())); - } - - if let Some(kind) = kind_filter { - params.insert("kind".to_string(), DataValue::Str(kind.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| TypesError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 7 { - let Some(project) = extract_string(&row[0]) else { - continue; - }; - let Some(module) = extract_string(&row[1]) else { - continue; - }; - let Some(name) = extract_string(&row[2]) else { - continue; - }; - let Some(kind) = extract_string(&row[3]) else { - continue; - }; - let params_str = extract_string(&row[4]).unwrap_or_default(); - let line = extract_i64(&row[5], 0); - let definition = extract_string(&row[6]).unwrap_or_default(); - - results.push(TypeInfo { - project, - module, - name, - kind, - params: params_str, - line, - definition, - }); - } - } - - Ok(results) -} diff --git a/src/queries/unused.rs b/src/queries/unused.rs deleted file mode 100644 index 070f534..0000000 --- a/src/queries/unused.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::error::Error; - -use cozo::DataValue; -use serde::Serialize; -use thiserror::Error; - -use crate::db::{extract_i64, extract_string, run_query, Params}; - -#[derive(Error, Debug)] -pub enum UnusedError { - #[error("Unused query failed: {message}")] - QueryFailed { message: String }, -} - -/// A function that is never called -#[derive(Debug, Clone, Serialize)] -pub struct UnusedFunction { - pub module: String, - pub name: String, - pub arity: i64, - pub kind: String, - pub file: String, - pub line: i64, -} - -/// Generated function name patterns to exclude (Elixir compiler-generated) -const GENERATED_PATTERNS: &[&str] = &[ - "__struct__", - "__using__", - "__before_compile__", - "__after_compile__", - "__on_definition__", - "__impl__", - "__info__", - "__protocol__", - "__deriving__", - "__changeset__", - "__schema__", - "__meta__", -]; - -pub fn find_unused_functions( - db: &cozo::DbInstance, - module_pattern: Option<&str>, - project: &str, - use_regex: bool, - private_only: bool, - public_only: bool, - exclude_generated: bool, - limit: u32, -) -> Result, Box> { - // Build optional module filter - let module_filter = match module_pattern { - Some(_) if use_regex => ", regex_matches(module, $module_pattern)".to_string(), - Some(_) => ", str_includes(module, $module_pattern)".to_string(), - None => String::new(), - }; - - // Build kind filter for private_only/public_only - let kind_filter = if private_only { - ", (kind == \"defp\" or kind == \"defmacrop\")".to_string() - } else if public_only { - ", (kind == \"def\" or kind == \"defmacro\")".to_string() - } else { - String::new() - }; - - // Find functions that exist in function_locations but are never called - // We use function_locations as the source of "defined functions" and check - // if they appear as a callee in the calls table - let script = format!( - r#" - # All defined functions - defined[module, name, arity, kind, file, start_line] := - *function_locations{{project, module, name, arity, kind, file, start_line}}, - project == $project - {module_filter} - {kind_filter} - - # All functions that are called (as callees) - called[module, name, arity] := - *calls{{project, callee_module, callee_function, callee_arity}}, - project == $project, - module = callee_module, - name = callee_function, - arity = callee_arity - - # Functions that are defined but never called - ?[module, name, arity, kind, file, line] := - defined[module, name, arity, kind, file, line], - not called[module, name, arity] - - :order module, name, arity - :limit {limit} - "#, - ); - - let mut params = Params::new(); - params.insert("project".to_string(), DataValue::Str(project.into())); - if let Some(pattern) = module_pattern { - params.insert("module_pattern".to_string(), DataValue::Str(pattern.into())); - } - - let rows = run_query(db, &script, params).map_err(|e| UnusedError::QueryFailed { - message: e.to_string(), - })?; - - let mut results = Vec::new(); - for row in rows.rows { - if row.len() >= 6 { - let Some(module) = extract_string(&row[0]) else { continue }; - let Some(name) = extract_string(&row[1]) else { continue }; - let arity = extract_i64(&row[2], 0); - let Some(kind) = extract_string(&row[3]) else { continue }; - let Some(file) = extract_string(&row[4]) else { continue }; - let line = extract_i64(&row[5], 0); - - // Filter out generated functions if requested - if exclude_generated && GENERATED_PATTERNS.iter().any(|p| name.starts_with(p)) { - continue; - } - - results.push(UnusedFunction { - module, - name, - arity, - kind, - file, - line, - }); - } - } - - Ok(results) -} diff --git a/src/test_macros.rs b/src/test_macros.rs deleted file mode 100644 index 021ee6d..0000000 --- a/src/test_macros.rs +++ /dev/null @@ -1,658 +0,0 @@ -//! Declarative macros for generating CLI parsing tests. -//! -//! This module provides macros to reduce boilerplate in CLI argument parsing tests. -//! Instead of writing repetitive test functions, you can declare the test cases -//! and let the macro generate the actual test code. - -/// Generate a test for default values when a command is invoked with minimal args. -#[macro_export] -macro_rules! cli_defaults_test { - ( - command: $cmd:literal, - variant: $variant:ident, - required_args: [$($req_arg:literal),*], - defaults: { - $($($def_field:ident).+ : $def_expected:expr),* $(,)? - } $(,)? - ) => { - #[rstest] - fn test_defaults() { - let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); - match args.command { - crate::commands::Command::$variant(cmd) => { - $( - assert_eq!(cmd.$($def_field).+, $def_expected, - concat!("Default value mismatch for field: ", stringify!($($def_field).+))); - )* - } - _ => panic!(concat!("Expected ", stringify!($variant), " command")), - } - } - }; -} - -/// Generate a single CLI option test. -#[macro_export] -macro_rules! cli_option_test { - ( - command: $cmd:literal, - variant: $variant:ident, - test_name: $test_name:ident, - args: [$($arg:literal),+], - field: $($field:ident).+, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name() { - let args = Args::try_parse_from([ - "code_search", - $cmd, - $($arg),+ - ]).unwrap(); - match args.command { - crate::commands::Command::$variant(cmd) => { - assert_eq!(cmd.$($field).+, $expected, - concat!("Field ", stringify!($($field).+), " mismatch")); - } - _ => panic!(concat!("Expected ", stringify!($variant), " command")), - } - } - }; -} - -/// Generate a single CLI option test with required args. -#[macro_export] -macro_rules! cli_option_test_with_required { - ( - command: $cmd:literal, - variant: $variant:ident, - required_args: [$($req_arg:literal),+], - test_name: $test_name:ident, - args: [$($arg:literal),+], - field: $($field:ident).+, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name() { - let args = Args::try_parse_from([ - "code_search", - $cmd, - $($req_arg,)+ - $($arg),+ - ]).unwrap(); - match args.command { - crate::commands::Command::$variant(cmd) => { - assert_eq!(cmd.$($field).+, $expected, - concat!("Field ", stringify!($($field).+), " mismatch")); - } - _ => panic!(concat!("Expected ", stringify!($variant), " command")), - } - } - }; -} - -/// Generate limit validation tests (zero rejected, max exceeded rejected, default value). -#[macro_export] -macro_rules! cli_limit_tests { - ( - command: $cmd:literal, - variant: $variant:ident, - required_args: [$($req_arg:literal),*], - limit: { - field: $($limit_field:ident).+, - default: $limit_default:expr, - max: $limit_max:expr $(,)? - } $(,)? - ) => { - #[rstest] - fn test_limit_default() { - let args = Args::try_parse_from(["code_search", $cmd, $($req_arg),*]).unwrap(); - match args.command { - crate::commands::Command::$variant(cmd) => { - assert_eq!(cmd.$($limit_field).+, $limit_default); - } - _ => panic!(concat!("Expected ", stringify!($variant), " command")), - } - } - - #[rstest] - fn test_limit_zero_rejected() { - let result = Args::try_parse_from([ - "code_search", - $cmd, - $($req_arg,)* - "--limit", - "0" - ]); - assert!(result.is_err(), "Limit of 0 should be rejected"); - } - - #[rstest] - fn test_limit_exceeds_max_rejected() { - let max_plus_one = ($limit_max + 1).to_string(); - let result = Args::try_parse_from([ - "code_search", - $cmd, - $($req_arg,)* - "--limit", - &max_plus_one - ]); - assert!(result.is_err(), - concat!("Limit exceeding ", stringify!($limit_max), " should be rejected")); - } - }; -} - -/// Generate a test that verifies a command requires a specific argument. -/// -/// # Example -/// -/// ```ignore -/// cli_required_arg_test! { -/// command: "search", -/// test_name: test_requires_pattern, -/// required_arg: "--pattern", -/// } -/// ``` -#[macro_export] -macro_rules! cli_required_arg_test { - ( - command: $cmd:literal, - test_name: $test_name:ident, - required_arg: $arg:literal $(,)? - ) => { - #[rstest] - fn $test_name() { - let result = Args::try_parse_from(["code_search", $cmd]); - assert!(result.is_err(), concat!("Command should require ", $arg)); - assert!( - result.unwrap_err().to_string().contains($arg), - concat!("Error should mention ", $arg) - ); - } - }; -} - -/// Generate a test that verifies parsing fails with specific invalid args. -/// -/// # Example -/// -/// ```ignore -/// cli_error_test! { -/// command: "search", -/// test_name: test_limit_zero_rejected, -/// args: ["--pattern", "test", "--limit", "0"], -/// } -/// ``` -#[macro_export] -macro_rules! cli_error_test { - ( - command: $cmd:literal, - test_name: $test_name:ident, - args: [$($arg:literal),+] $(,)? - ) => { - #[rstest] - fn $test_name() { - let result = Args::try_parse_from([ - "code_search", - $cmd, - $($arg),+ - ]); - assert!(result.is_err()); - } - }; -} - -// ============================================================================= -// Execute Test Macros -// ============================================================================= - -/// Generate a fixture that creates a populated test database. -/// -/// This creates the standard `populated_db` fixture used by execute tests. -/// For inline JSON content. -#[macro_export] -macro_rules! execute_test_fixture { - ( - fixture_name: $name:ident, - json: $json:expr, - project: $project:literal $(,)? - ) => { - #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::setup_test_db($json, $project) - } - }; -} - -/// Generate a fixture using a shared fixture file. -/// -/// Available fixtures: `call_graph`, `type_signatures`, `structs` -/// -/// # Example -/// ```ignore -/// crate::shared_fixture! { -/// fixture_name: populated_db, -/// fixture_type: call_graph, -/// project: "test_project", -/// } -/// ``` -#[macro_export] -macro_rules! shared_fixture { - ( - fixture_name: $name:ident, - fixture_type: call_graph, - project: $project:literal $(,)? - ) => { - #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::call_graph_db($project) - } - }; - ( - fixture_name: $name:ident, - fixture_type: type_signatures, - project: $project:literal $(,)? - ) => { - #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::type_signatures_db($project) - } - }; - ( - fixture_name: $name:ident, - fixture_type: structs, - project: $project:literal $(,)? - ) => { - #[fixture] - fn $name() -> cozo::DbInstance { - crate::test_utils::structs_db($project) - } - }; -} - -/// Generate a test that verifies command execution against an empty database fails. -#[macro_export] -macro_rules! execute_empty_db_test { - ( - cmd_type: $cmd_type:ty, - cmd: $cmd:expr $(,)? - ) => { - #[rstest] - fn test_empty_db() { - let result = crate::test_utils::execute_on_empty_db($cmd); - assert!(result.is_err()); - } - }; -} - -/// Generate an execute test with custom assertions. -/// -/// This is the core macro for execute tests. It handles the boilerplate of -/// executing a command against a fixture and lets you write custom assertions. -/// -/// # Example -/// ```ignore -/// execute_test! { -/// test_name: test_search_finds_modules, -/// fixture: populated_db, -/// cmd: SearchCmd { -/// pattern: "MyApp".to_string(), -/// kind: SearchKind::Modules, -/// project: "test_project".to_string(), -/// limit: 100, -/// regex: false, -/// }, -/// assertions: |result| { -/// assert_eq!(result.modules.len(), 2); -/// assert_eq!(result.kind, "modules"); -/// }, -/// } -/// ``` -#[macro_export] -macro_rules! execute_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - assertions: |$result:ident| $assertions:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let $result = $cmd.execute(&$fixture).expect("Execute should succeed"); - $assertions - } - }; -} - -/// Generate a test that verifies command returns empty results for no match. -/// -/// # Example -/// ```ignore -/// execute_no_match_test! { -/// test_name: test_search_no_match, -/// fixture: populated_db, -/// cmd: SearchCmd { pattern: "NonExistent".into(), ... }, -/// empty_field: modules, -/// } -/// ``` -#[macro_export] -macro_rules! execute_no_match_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - empty_field: $field:ident $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$field.is_empty(), concat!(stringify!($field), " should be empty")); - } - }; -} - -/// Generate a test that verifies result count. -/// -/// # Example -/// ```ignore -/// execute_count_test! { -/// test_name: test_search_finds_two, -/// fixture: populated_db, -/// cmd: SearchCmd { ... }, -/// field: modules, -/// expected: 2, -/// } -/// ``` -#[macro_export] -macro_rules! execute_count_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - field: $field:ident, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert_eq!(result.$field.len(), $expected, - concat!("Expected ", stringify!($expected), " ", stringify!($field))); - } - }; -} - -/// Generate a test that verifies a field value on the result. -/// -/// # Example -/// ```ignore -/// execute_field_test! { -/// test_name: test_search_kind, -/// fixture: populated_db, -/// cmd: SearchCmd { kind: SearchKind::Modules, ... }, -/// field: kind, -/// expected: "modules", -/// } -/// ``` -#[macro_export] -macro_rules! execute_field_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - field: $field:ident, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert_eq!(result.$field, $expected, - concat!("Field ", stringify!($field), " mismatch")); - } - }; -} - -/// Generate a test that verifies a field on the first result item. -/// -/// # Example -/// ```ignore -/// execute_first_item_test! { -/// test_name: test_first_function_name, -/// fixture: populated_db, -/// cmd: SearchCmd { ... }, -/// collection: functions, -/// field: name, -/// expected: "get_user", -/// } -/// ``` -#[macro_export] -macro_rules! execute_first_item_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - collection: $collection:ident, - field: $field:ident, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(!result.$collection.is_empty(), concat!(stringify!($collection), " should not be empty")); - assert_eq!(result.$collection[0].$field, $expected, - concat!("First item ", stringify!($field), " mismatch")); - } - }; -} - -/// Generate a test that verifies all items match a condition. -/// -/// # Example -/// ```ignore -/// execute_all_match_test! { -/// test_name: test_all_from_project, -/// fixture: populated_db, -/// cmd: SearchCmd { project: "test_project".into(), ... }, -/// collection: modules, -/// condition: |item| item.project == "test_project", -/// } -/// ``` -#[macro_export] -macro_rules! execute_all_match_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - collection: $collection:ident, - condition: |$item:ident| $cond:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$collection.iter().all(|$item| $cond), - concat!("Not all ", stringify!($collection), " matched condition")); - } - }; -} - -/// Generate a test that verifies limit is respected. -/// -/// # Example -/// ```ignore -/// execute_limit_test! { -/// test_name: test_respects_limit, -/// fixture: populated_db, -/// cmd: SearchCmd { limit: 1, ... }, -/// collection: modules, -/// limit: 1, -/// } -/// ``` -#[macro_export] -macro_rules! execute_limit_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - cmd: $cmd:expr, - collection: $collection:ident, - limit: $limit:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: cozo::DbInstance) { - use crate::commands::Execute; - let result = $cmd.execute(&$fixture).expect("Execute should succeed"); - assert!(result.$collection.len() <= $limit, - concat!("Expected at most ", stringify!($limit), " ", stringify!($collection))); - } - }; -} - -// ============================================================================= -// Output Test Macros -// ============================================================================= - -/// Generate a test that verifies table output matches expected string. -/// -/// Works with rstest fixtures by accepting a fixture parameter. -/// -/// # Example -/// ```ignore -/// output_table_test! { -/// test_name: test_to_table_empty, -/// fixture: empty_result, -/// fixture_type: SearchResult, -/// expected: EMPTY_TABLE_OUTPUT, -/// } -/// ``` -#[macro_export] -macro_rules! output_table_test { - // With format parameter (Json, Toon) - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - fixture_type: $fixture_type:ty, - expected: $expected:expr, - format: $format:ident $(,)? - ) => { - #[rstest] - fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; - assert_eq!($fixture.format(OutputFormat::$format), $expected); - } - }; - // Default table format - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - fixture_type: $fixture_type:ty, - expected: $expected:expr $(,)? - ) => { - #[rstest] - fn $test_name($fixture: $fixture_type) { - use crate::output::Outputable; - assert_eq!($fixture.to_table(), $expected); - } - }; -} - -/// Generate a test that verifies table output contains expected strings. -/// -/// Use this when exact string matching is too brittle. -#[macro_export] -macro_rules! output_table_contains_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - fixture_type: $fixture_type:ty, - contains: [$($needle:literal),* $(,)?] $(,)? - ) => { - #[rstest] - fn $test_name($fixture: $fixture_type) { - use crate::output::Outputable; - let output = $fixture.to_table(); - $( - assert!(output.contains($needle), concat!("Table output should contain: ", $needle)); - )* - } - }; -} - -/// Generate a test that verifies JSON output is valid and contains expected fields. -/// -/// # Example -/// ```ignore -/// output_json_test! { -/// test_name: test_format_json, -/// fixture: single_result, -/// fixture_type: SearchResult, -/// assertions: { -/// "pattern": "MyApp", -/// "modules".len(): 2, -/// }, -/// } -/// ``` -#[macro_export] -macro_rules! output_json_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - fixture_type: $fixture_type:ty, - assertions: { $($field:literal : $expected:expr),* $(,)? } $(,)? - ) => { - #[rstest] - fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; - let output = $fixture.format(OutputFormat::Json); - let parsed: serde_json::Value = serde_json::from_str(&output) - .expect("Should produce valid JSON"); - $( - assert_eq!(parsed[$field], $expected, concat!("JSON field mismatch: ", $field)); - )* - } - }; -} - -/// Generate a test that verifies Toon output contains expected strings. -/// -/// # Example -/// ```ignore -/// output_toon_test! { -/// test_name: test_format_toon, -/// fixture: single_result, -/// fixture_type: SearchResult, -/// contains: ["pattern: MyApp", "modules["], -/// } -/// ``` -#[macro_export] -macro_rules! output_toon_test { - ( - test_name: $test_name:ident, - fixture: $fixture:ident, - fixture_type: $fixture_type:ty, - contains: [$($needle:literal),* $(,)?] $(,)? - ) => { - #[rstest] - fn $test_name($fixture: $fixture_type) { - use crate::output::{Outputable, OutputFormat}; - let output = $fixture.format(OutputFormat::Toon); - $( - assert!(output.contains($needle), concat!("Toon output should contain: ", $needle)); - )* - } - }; -} - -#[cfg(test)] -mod tests { - //! Tests for the test macros themselves. - //! - //! These verify that the macros compile and generate working tests. - - // We can't easily test macros here since they generate test functions, - // but we can at least verify they compile by using them in actual test modules. -} diff --git a/src/test_utils.rs b/src/test_utils.rs deleted file mode 100644 index 10da5b5..0000000 --- a/src/test_utils.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Shared test utilities for execute and integration tests. -//! -//! This module provides common helpers used across command execute tests. - -use std::io::Write; - -use cozo::DbInstance; -use tempfile::NamedTempFile; - -use crate::queries::import::import_json_str; -use crate::commands::Execute; -use crate::db::open_mem_db; - -/// Create a temporary file containing the given content. -/// -/// Used to create JSON files for importing test data. -pub fn create_temp_json_file(content: &str) -> NamedTempFile { - let mut file = NamedTempFile::new().expect("Failed to create temp file"); - file.write_all(content.as_bytes()) - .expect("Failed to write temp file"); - file -} - -/// Create an in-memory database and import JSON content. -/// -/// This is the standard setup for execute tests: create an in-memory DB, -/// import test data, return the DB instance for command execution. -pub fn setup_test_db(json_content: &str, project: &str) -> DbInstance { - let db = open_mem_db(); - import_json_str(&db, json_content, project).expect("Import should succeed"); - db -} - -/// Execute a command against a database and return the result. -pub fn execute_cmd(cmd: C, db: &DbInstance) -> Result> { - cmd.execute(db) -} - -/// Execute a command against an empty (uninitialized) database. -/// -/// Used to verify commands fail gracefully on empty DBs. -pub fn execute_on_empty_db(cmd: C) -> Result> { - let db = open_mem_db(); - cmd.execute(&db) -} - -// ============================================================================= -// Fixture-based helpers -// ============================================================================= - -use crate::fixtures; - -/// Create a test database with call graph data. -/// -/// Use for: trace, reverse_trace, calls_from, calls_to, path, hotspots, -/// unused, depends_on, depended_by -pub fn call_graph_db(project: &str) -> DbInstance { - setup_test_db(fixtures::CALL_GRAPH, project) -} - -/// Create a test database with type signature data. -/// -/// Use for: search (functions kind), function -pub fn type_signatures_db(project: &str) -> DbInstance { - setup_test_db(fixtures::TYPE_SIGNATURES, project) -} - -/// Create a test database with struct definitions. -/// -/// Use for: struct command -pub fn structs_db(project: &str) -> DbInstance { - setup_test_db(fixtures::STRUCTS, project) -} - -// ============================================================================= -// Output fixture helpers -// ============================================================================= - -use std::path::Path; - -/// Load a fixture file from src/fixtures/output// -pub fn load_output_fixture(command: &str, name: &str) -> String { - let fixture_path = Path::new(env!("CARGO_MANIFEST_DIR")) - .join("src/fixtures/output") - .join(command) - .join(name); - - std::fs::read_to_string(&fixture_path) - .unwrap_or_else(|e| panic!("Failed to read fixture {}: {}", fixture_path.display(), e)) -} diff --git a/src/types/call.rs b/src/types/call.rs deleted file mode 100644 index 829c100..0000000 --- a/src/types/call.rs +++ /dev/null @@ -1,332 +0,0 @@ -//! Core types for representing function calls. - -use std::rc::Rc; -use serde::{Serialize, Serializer}; - -/// A function reference with optional definition location and type information. -/// Queries populate only the fields they need - optional fields are skipped during serialization. -/// Uses Rc for module and function names to reduce memory allocations when -/// the same names appear multiple times (which is typical in call graphs). -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FunctionRef { - pub module: Rc, - pub name: Rc, - pub arity: i64, - pub kind: Option>, - pub file: Option>, - pub start_line: Option, - pub end_line: Option, - pub args: Option>, - pub return_type: Option>, -} - -impl Serialize for FunctionRef { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - use serde::ser::SerializeStruct; - let mut state = serializer.serialize_struct("FunctionRef", 9)?; - state.serialize_field("module", self.module.as_ref())?; - state.serialize_field("name", self.name.as_ref())?; - state.serialize_field("arity", &self.arity)?; - if self.kind.is_some() { - state.serialize_field("kind", &self.kind.as_deref())?; - } - if self.file.is_some() { - state.serialize_field("file", &self.file.as_deref())?; - } - if self.start_line.is_some() { - state.serialize_field("start_line", &self.start_line)?; - } - if self.end_line.is_some() { - state.serialize_field("end_line", &self.end_line)?; - } - if self.args.is_some() { - state.serialize_field("args", &self.args.as_deref())?; - } - if self.return_type.is_some() { - state.serialize_field("return_type", &self.return_type.as_deref())?; - } - state.end() - } -} - -impl FunctionRef { - /// Create a minimal function reference (module, name, arity only). - pub fn new(module: impl Into>, name: impl Into>, arity: i64) -> Self { - Self { - module: module.into(), - name: name.into(), - arity, - kind: None, - file: None, - start_line: None, - end_line: None, - args: None, - return_type: None, - } - } - - /// Create a function reference with full definition info. - pub fn with_definition( - module: impl Into>, - name: impl Into>, - arity: i64, - kind: impl Into>, - file: impl Into>, - start_line: i64, - end_line: i64, - ) -> Self { - Self { - module: module.into(), - name: name.into(), - arity, - kind: Some(kind.into()), - file: Some(file.into()), - start_line: Some(start_line), - end_line: Some(end_line), - args: None, - return_type: None, - } - } - - /// Create a function reference with type information. - pub fn with_types( - module: impl Into>, - name: impl Into>, - arity: i64, - kind: impl Into>, - file: impl Into>, - start_line: i64, - end_line: i64, - args: impl Into>, - return_type: impl Into>, - ) -> Self { - Self { - module: module.into(), - name: name.into(), - arity, - kind: Some(kind.into()), - file: Some(file.into()), - start_line: Some(start_line), - end_line: Some(end_line), - args: Some(args.into()), - return_type: Some(return_type.into()), - } - } - - /// Format as "name/arity" or "Module.name/arity" if module differs from context. - pub fn format_name(&self, context_module: Option<&str>) -> String { - if context_module == Some(self.module.as_ref()) { - format!("{}/{}", self.name, self.arity) - } else { - format!("{}.{}/{}", self.module, self.name, self.arity) - } - } - - /// Format location as "L42:50" or "file.ex:L42:50". - /// Returns None if no location info available. - pub fn format_location(&self, context_file: Option<&str>) -> Option { - let (start, end) = match (self.start_line, self.end_line) { - (Some(s), Some(e)) => (s, e), - _ => return None, - }; - - let file = self.file.as_deref()?; - let filename = file.rsplit('/').next().unwrap_or(file); - let context_filename = context_file - .map(|f| f.rsplit('/').next().unwrap_or(f)); - - if context_filename == Some(filename) { - Some(format!("L{}:{}", start, end)) - } else { - Some(format!("{}:L{}:{}", filename, start, end)) - } - } - - /// Format kind as "[def]" or empty string if no kind. - pub fn format_kind(&self) -> String { - self.kind - .as_ref() - .filter(|k| !k.is_empty()) - .map(|k| format!(" [{}]", k)) - .unwrap_or_default() - } -} - -/// A directed call relationship. -#[derive(Debug, Clone, Serialize)] -pub struct Call { - pub caller: FunctionRef, - pub callee: FunctionRef, - pub line: i64, - #[serde(skip_serializing_if = "Option::is_none")] - pub call_type: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub depth: Option, -} - -impl Call { - /// Check if this is a struct construction call (e.g., %MyStruct{}). - pub fn is_struct_call(&self) -> bool { - self.callee.name.as_ref() == "%" - } - - /// Format as outgoing call: "→ @ L37 name/arity [kind] (location)" - pub fn format_outgoing(&self, context_module: &str, context_file: &str) -> String { - let name = self.callee.format_name(Some(context_module)); - let kind = self.callee.format_kind(); - let location = self - .callee - .format_location(Some(context_file)) - .map(|loc| format!(" ({})", loc)) - .unwrap_or_default(); - - format!("→ @ L{} {}{}{}", self.line, name, kind, location) - } - - /// Format as incoming call: "← @ L37 name/arity [kind] (location)" - pub fn format_incoming(&self, context_module: &str, context_file: &str) -> String { - let name = self.caller.format_name(Some(context_module)); - let kind = self.caller.format_kind(); - let location = self - .caller - .format_location(Some(context_file)) - .map(|loc| format!(" ({})", loc)) - .unwrap_or_default(); - - format!("← @ L{} {}{}{}", self.line, name, kind, location) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_function_ref_format_name_same_module() { - let func = FunctionRef::new("MyModule", "my_func", 2); - assert_eq!(func.format_name(Some("MyModule")), "my_func/2"); - } - - #[test] - fn test_function_ref_format_name_different_module() { - let func = FunctionRef::new("OtherModule", "other_func", 1); - assert_eq!( - func.format_name(Some("MyModule")), - "OtherModule.other_func/1" - ); - } - - #[test] - fn test_function_ref_format_location_same_file() { - let func = FunctionRef::with_definition( - "MyModule", - "my_func", - 2, - "def", - "/path/to/my_module.ex", - 10, - 20, - ); - assert_eq!( - func.format_location(Some("/other/path/my_module.ex")), - Some("L10:20".to_string()) - ); - } - - #[test] - fn test_function_ref_format_location_different_file() { - let func = FunctionRef::with_definition( - "MyModule", - "my_func", - 2, - "def", - "/path/to/my_module.ex", - 10, - 20, - ); - assert_eq!( - func.format_location(Some("/path/to/other.ex")), - Some("my_module.ex:L10:20".to_string()) - ); - } - - #[test] - fn test_call_format_outgoing() { - let call = Call { - caller: FunctionRef::with_definition( - "MyModule", - "caller_func", - 1, - "def", - "/path/to/my_module.ex", - 10, - 30, - ), - callee: FunctionRef::with_definition( - "MyModule", - "callee_func", - 2, - "defp", - "/path/to/my_module.ex", - 40, - 50, - ), - line: 25, - call_type: None, - depth: None, - }; - - assert_eq!( - call.format_outgoing("MyModule", "/path/to/my_module.ex"), - "→ @ L25 callee_func/2 [defp] (L40:50)" - ); - } - - #[test] - fn test_call_format_outgoing_different_module() { - let call = Call { - caller: FunctionRef::new("MyModule", "caller_func", 1), - callee: FunctionRef::with_definition( - "OtherModule", - "other_func", - 0, - "def", - "/path/to/other.ex", - 5, - 15, - ), - line: 12, - call_type: None, - depth: None, - }; - - assert_eq!( - call.format_outgoing("MyModule", "/path/to/my_module.ex"), - "→ @ L12 OtherModule.other_func/0 [def] (other.ex:L5:15)" - ); - } - - #[test] - fn test_is_struct_call() { - let struct_call = Call { - caller: FunctionRef::new("MyModule", "func", 1), - callee: FunctionRef::new("MyStruct", "%", 2), - line: 10, - call_type: None, - depth: None, - }; - assert!(struct_call.is_struct_call()); - - let normal_call = Call { - caller: FunctionRef::new("MyModule", "func", 1), - callee: FunctionRef::new("OtherModule", "other", 0), - line: 10, - call_type: None, - depth: None, - }; - assert!(!normal_call.is_struct_call()); - } -} diff --git a/src/types/mod.rs b/src/types/mod.rs deleted file mode 100644 index 3fe761f..0000000 --- a/src/types/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Shared types for call graph data. - -use std::rc::Rc; - -mod call; -mod results; -mod trace; - -pub use call::{Call, FunctionRef}; -pub use results::{ModuleGroupResult, ModuleCollectionResult, ModuleGroup}; -pub use trace::{TraceDirection, TraceEntry, TraceResult}; - -/// Type alias for shared, reference-counted strings. -/// Used throughout FunctionRef and Call structures to reduce memory allocations -/// when the same module/function names appear multiple times. -pub type SharedStr = Rc; diff --git a/src/types/results.rs b/src/types/results.rs deleted file mode 100644 index b070c46..0000000 --- a/src/types/results.rs +++ /dev/null @@ -1,38 +0,0 @@ -use serde::Serialize; - -/// Generic result structure for commands that group entries by module -/// Used by calls_from, calls_to, depends_on, depended_by -#[derive(Debug, Default, Serialize)] -pub struct ModuleGroupResult { - pub module_pattern: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub function_pattern: Option, - pub total_items: usize, - pub items: Vec>, -} - -/// Generic result structure for commands with module grouping and multiple filter options -/// Used by function, specs, types -#[derive(Debug, Default, Serialize)] -pub struct ModuleCollectionResult { - pub module_pattern: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub function_pattern: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub kind_filter: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub name_filter: Option, - pub total_items: usize, - pub items: Vec>, -} - -/// A module with a collection of generic entries -#[derive(Debug, Default, Serialize)] -pub struct ModuleGroup { - pub name: String, - #[serde(skip_serializing_if = "String::is_empty")] - pub file: String, - pub entries: Vec, - #[serde(skip_serializing_if = "Option::is_none")] - pub function_count: Option, -} diff --git a/src/types/trace.rs b/src/types/trace.rs deleted file mode 100644 index e971fc9..0000000 --- a/src/types/trace.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! Unified types for trace and reverse-trace commands. - -use serde::Serialize; - -/// Direction of trace traversal -#[derive(Debug, Clone, Copy, Default, Serialize)] -#[serde(rename_all = "lowercase")] -pub enum TraceDirection { - #[default] - Forward, - Backward, -} - -/// A single entry in the trace tree (flattened representation) -#[derive(Debug, Clone, Serialize)] -pub struct TraceEntry { - pub module: String, - pub function: String, - pub arity: i64, - pub kind: String, - pub start_line: i64, - pub end_line: i64, - pub file: String, - pub depth: i64, - pub line: i64, // Line where the call happens - #[serde(skip_serializing_if = "Option::is_none")] - pub parent_index: Option, // Index in entries list of parent -} - -/// Result of trace or reverse-trace command execution -#[derive(Debug, Default, Serialize)] -pub struct TraceResult { - pub module: String, - pub function: String, - pub max_depth: u32, - pub direction: TraceDirection, - pub total_items: usize, // total_calls or total_callers - pub entries: Vec, -} - -impl TraceResult { - /// Create an empty trace result - pub fn empty(module: String, function: String, max_depth: u32, direction: TraceDirection) -> Self { - Self { - module, - function, - max_depth, - direction, - total_items: 0, - entries: vec![], - } - } -} diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 6bd1d3e..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,684 +0,0 @@ -//! Utility functions for code search operations. - -use std::collections::BTreeMap; -use regex::Regex; -use crate::types::{ModuleGroup, Call}; -use crate::dedup::sort_and_deduplicate; - -/// Builds SQL WHERE clause conditions for query patterns (exact or regex matching) -/// -/// Handles the common pattern of building conditions that differ between exact and regex modes. -/// Supports different field prefixes and optional leading comma. -/// -/// # Examples -/// -/// ```ignore -/// let builder = ConditionBuilder::new("module", "module_pattern"); -/// let cond = builder.build(false); // "module == $module_pattern" -/// let cond = builder.build(true); // "regex_matches(module, $module_pattern)" -/// ``` -pub struct ConditionBuilder { - field_name: String, - param_name: String, - with_leading_comma: bool, -} - -impl ConditionBuilder { - /// Creates a new condition builder for a field with exact/regex matching - /// - /// # Arguments - /// * `field_name` - The SQL field name (e.g., "module", "caller_module") - /// * `param_name` - The parameter name (e.g., "module_pattern", "function_pattern") - pub fn new(field_name: &str, param_name: &str) -> Self { - Self { - field_name: field_name.to_string(), - param_name: param_name.to_string(), - with_leading_comma: false, - } - } - - /// Adds a leading comma to the condition (useful for mid-query conditions) - pub fn with_leading_comma(mut self) -> Self { - self.with_leading_comma = true; - self - } - - /// Builds the condition string based on use_regex flag - /// - /// When `use_regex` is true, uses `regex_matches()`. - /// When `use_regex` is false, uses exact matching with `==`. - /// - /// # Arguments - /// * `use_regex` - Whether to use regex matching - /// - /// # Returns - /// A condition string ready to be interpolated into a SQL query - pub fn build(&self, use_regex: bool) -> String { - let prefix = if self.with_leading_comma { ", " } else { "" }; - - if use_regex { - format!( - "{}regex_matches({}, ${})", - prefix, self.field_name, self.param_name - ) - } else { - format!("{}{} == ${}", prefix, self.field_name, self.param_name) - } - } -} - -/// Builder for optional SQL conditions (function, arity, etc.) -/// -/// Handles the pattern of generating conditions only when values are present. -/// For function-matching conditions, supports both exact and regex matching. -pub struct OptionalConditionBuilder { - field_name: String, - param_name: String, - with_leading_comma: bool, - when_none: Option, // Alternative condition when value is None - supports_regex: bool, // Whether to use regex_matches when value is present -} - -impl OptionalConditionBuilder { - /// Creates a new optional condition builder - /// - /// # Arguments - /// * `field_name` - The SQL field name - /// * `param_name` - The parameter name - pub fn new(field_name: &str, param_name: &str) -> Self { - Self { - field_name: field_name.to_string(), - param_name: param_name.to_string(), - with_leading_comma: false, - when_none: None, - supports_regex: false, - } - } - - /// Enables regex matching (uses regex_matches when value is present) - pub fn with_regex(mut self) -> Self { - self.supports_regex = true; - self - } - - /// Adds a leading comma - pub fn with_leading_comma(mut self) -> Self { - self.with_leading_comma = true; - self - } - - /// Sets an alternative condition when the value is None (e.g., "true" for no-op) - pub fn when_none(mut self, condition: &str) -> Self { - self.when_none = Some(condition.to_string()); - self - } - - /// Builds the condition string - /// - /// # Arguments - /// * `has_value` - Whether the optional value is present - /// * `use_regex` - Whether to use regex matching (only matters if supports_regex is true) - /// - /// # Returns - /// A condition string, or empty string if no value and no alternative - pub fn build_with_regex(&self, has_value: bool, use_regex: bool) -> String { - let prefix = if self.with_leading_comma { ", " } else { "" }; - - if has_value { - if self.supports_regex && use_regex { - format!( - "{}regex_matches({}, ${})", - prefix, self.field_name, self.param_name - ) - } else { - format!("{}{} == ${}", prefix, self.field_name, self.param_name) - } - } else { - self.when_none - .as_ref() - .map(|cond| format!("{}{}", prefix, cond)) - .unwrap_or_default() - } - } - - /// Builds the condition string (non-regex version, for backward compatibility) - /// - /// # Arguments - /// * `has_value` - Whether the optional value is present - /// - /// # Returns - /// A condition string, or empty string if no value and no alternative - pub fn build(&self, has_value: bool) -> String { - self.build_with_regex(has_value, false) - } -} - -/// Groups items by module into a structured result -/// -/// Transforms a vector of source items into (module, entry) tuples and groups them by module -/// using BTreeMap for consistent ordering. Files default to empty string. -/// -/// # Arguments -/// * `items` - Vector of items to transform and group -/// * `transform` - Closure that converts source items to (module_name, entry) tuples -/// -/// # Returns -/// A vector of ModuleGroup structs, one per module in sorted order -pub fn group_by_module(items: Vec, transform: F) -> Vec> -where - F: Fn(T) -> (String, E), -{ - group_by_module_with_file(items, |item| { - let (module, entry) = transform(item); - (module, entry, String::new()) - }) -} - -/// Groups items by module with optional file tracking -/// -/// Like `group_by_module` but allows specifying a file path for each item. -/// -/// # Arguments -/// * `items` - Vector of items to transform and group -/// * `transform` - Closure that converts source items to (module_name, entry, file) tuples -/// -/// # Returns -/// A vector of ModuleGroup structs, one per module in sorted order -pub fn group_by_module_with_file(items: Vec, transform: F) -> Vec> -where - F: Fn(T) -> (String, E, String), -{ - let mut module_map: BTreeMap)> = BTreeMap::new(); - - for item in items { - let (module, entry, file) = transform(item); - let entry_data = module_map - .entry(module) - .or_insert_with(|| (file.clone(), Vec::new())); - entry_data.1.push(entry); - } - - module_map - .into_iter() - .map(|(name, (file, entries))| ModuleGroup { name, file, entries, function_count: None }) - .collect() -} - -/// Groups calls by module and function key, applying sort/deduplicate to each group. -/// -/// This is the primary helper for processing call data that follows this pattern: -/// 1. Receive Vec from a query -/// 2. Group by module and function key using closures -/// 3. Apply sort_and_deduplicate to each function's calls -/// 4. Convert to ModuleGroupResult using entry_fn and file_fn -/// -/// # Arguments -/// * `calls` - Vector of Call objects to group -/// * `module_fn` - Closure that extracts the module name from a Call -/// * `key_fn` - Closure that extracts the grouping key (e.g., function info) from a Call -/// * `sort_cmp` - Comparator closure for sorting calls (e.g., by line number) -/// * `dedup_key` - Closure that extracts the deduplication key from a Call -/// * `entry_fn` - Closure that converts (key, sorted/deduped calls) to an entry -/// * `file_fn` - Closure that determines the file path for a module group -/// -/// # Returns -/// A tuple of (total_items_count, Vec>) -/// -/// # Example -/// ```ignore -/// let (total, groups) = group_calls( -/// calls, -/// |call| call.caller.module.clone(), // group by caller module -/// |call| (call.caller.name.clone(), call.caller.arity), // key by (name, arity) -/// |a, b| a.line.cmp(&b.line), // sort by line -/// |c| (c.callee.module.clone(), c.callee.name.clone()), // dedup by callee -/// |(name, arity), calls| MyEntry { name, arity, calls }, // build entry -/// |_module, _map| String::new(), // no file tracking -/// ); -/// ``` -pub fn group_calls( - calls: Vec, - module_fn: MF, - key_fn: KF, - sort_cmp: SC, - dedup_key: DK, - entry_fn: EF, - file_fn: FF, -) -> (usize, Vec>) -where - K: Ord, - MF: Fn(&Call) -> String, - KF: Fn(&Call) -> K, - SC: FnMut(&Call, &Call) -> std::cmp::Ordering + Clone, - DK: Fn(&Call) -> D + Clone, - D: Eq + std::hash::Hash, - EF: Fn(K, Vec) -> E, - FF: Fn(&str, &BTreeMap>) -> String, -{ - // Group by module -> key -> calls - let mut by_module: BTreeMap>> = BTreeMap::new(); - for call in calls { - let module = module_fn(&call); - let key = key_fn(&call); - by_module.entry(module).or_default().entry(key).or_default().push(call); - } - - // Convert to ModuleGroups with sort/dedup, counting total after dedup - let mut total_items = 0; - let items = by_module.into_iter().map(|(module_name, mut functions_map)| { - let file = file_fn(&module_name, &functions_map); - - // Sort and deduplicate each function's calls - for calls in functions_map.values_mut() { - sort_and_deduplicate(calls, sort_cmp.clone(), dedup_key.clone()); - total_items += calls.len(); - } - - let entries: Vec = functions_map.into_iter() - .map(|(key, calls)| entry_fn(key, calls)) - .collect(); - - ModuleGroup { name: module_name, file, entries, function_count: None } - }).collect(); - - (total_items, items) -} - -/// Converts a two-level nested map into Vec>. -/// -/// Handles the common pattern of grouping calls by module and function, -/// then converting the nested structure into a flat Vec of ModuleGroups. -/// -/// # Arguments -/// * `by_module` - A BTreeMap of modules to (function_key → calls) maps -/// * `entry_builder` - Closure that converts (function_key, calls) to an entry -/// * `file_strategy` - Closure that determines the file path for a module group -/// -/// # Returns -/// A vector of ModuleGroup structs, one per module in sorted order -/// -/// # Example -/// ```ignore -/// let mut by_module: BTreeMap>> = /* ... */; -/// let groups = convert_to_module_groups( -/// by_module, -/// |(name, arity), calls| { -/// CallEntry { -/// function_name: name, -/// arity, -/// count: calls.len(), -/// } -/// }, -/// |_module, _map| String::new() // No file tracking -/// ); -/// ``` -pub fn convert_to_module_groups( - by_module: BTreeMap>>, - entry_builder: F, - file_strategy: FileF, -) -> Vec> -where - FK: Ord, - F: Fn(FK, Vec) -> E, - FileF: Fn(&str, &BTreeMap>) -> String, -{ - by_module - .into_iter() - .map(|(module_name, functions_map)| { - let file = file_strategy(&module_name, &functions_map); - - let entries: Vec = functions_map - .into_iter() - .map(|(key, calls)| entry_builder(key, calls)) - .collect(); - - ModuleGroup { - name: module_name, - file, - entries, - function_count: None, - } - }) - .collect() -} - -// ============================================================================= -// Type Formatting Utilities -// ============================================================================= - -/// Formats an Elixir type definition for display. -/// -/// Transforms struct type definitions from the internal representation: -/// `@type t() :: %{__struct__: ModuleName, field1: type1, field2: type2}` -/// -/// To the more readable Elixir syntax: -/// ```text -/// @type t() :: %ModuleName{ -/// field1: type1, -/// field2: type2 -/// } -/// ``` -/// -/// # Arguments -/// * `definition` - The raw type definition string from the database -/// -/// # Returns -/// The formatted type definition string -pub fn format_type_definition(definition: &str) -> String { - // Check if this is a struct type definition - if let Some(formatted) = try_format_struct_type(definition) { - return formatted; - } - - // Return as-is if no transformation needed - definition.to_string() -} - -/// Attempts to format a struct type definition. -/// -/// Returns `Some(formatted_string)` if the definition contains a struct pattern, -/// otherwise returns `None`. -fn try_format_struct_type(definition: &str) -> Option { - // Pattern to match: %{__struct__: ModuleName} or %{__struct__: ModuleName, ...} - // This captures the struct module name and optionally the remaining fields - let struct_pattern = Regex::new( - r"%\{\s*__struct__:\s*([A-Za-z][A-Za-z0-9_.]*(?:\.[A-Za-z][A-Za-z0-9_]*)*)\s*(?:,\s*(.*))?\}" - ).ok()?; - - if let Some(caps) = struct_pattern.captures(definition) { - let module_name = caps.get(1)?.as_str(); - let fields_str = caps.get(2).map(|m| m.as_str().trim()).unwrap_or(""); - - // Parse the fields - let fields = parse_type_fields(fields_str); - - if fields.is_empty() { - // Empty struct - let formatted_struct = format!("%{}{{}}", module_name); - return Some(definition.replace(caps.get(0)?.as_str(), &formatted_struct)); - } - - // Format with multi-line for readability - let formatted_fields = fields - .iter() - .map(|(name, typ)| format!(" {}: {}", name, typ)) - .collect::>() - .join(",\n"); - - let formatted_struct = format!("%{}{{\n{}\n}}", module_name, formatted_fields); - - // Replace the struct pattern in the original definition - Some(definition.replace(caps.get(0)?.as_str(), &formatted_struct)) - } else { - None - } -} - -/// Parses a comma-separated list of type fields. -/// -/// Handles nested types with parentheses, braces, and brackets. -/// For example: `name: String.t(), list: list(integer()), map: map()` -/// -/// # Arguments -/// * `fields_str` - The raw fields string without outer braces -/// -/// # Returns -/// A vector of (field_name, field_type) tuples -fn parse_type_fields(fields_str: &str) -> Vec<(String, String)> { - let mut fields = Vec::new(); - let mut current_field = String::new(); - let mut depth = 0; // Track nesting depth for (), {}, [] - - for ch in fields_str.chars() { - match ch { - '(' | '{' | '[' => { - depth += 1; - current_field.push(ch); - } - ')' | '}' | ']' => { - depth -= 1; - current_field.push(ch); - } - ',' if depth == 0 => { - // Top-level comma - this is a field separator - if let Some((name, typ)) = parse_single_field(¤t_field) { - fields.push((name, typ)); - } - current_field.clear(); - } - _ => { - current_field.push(ch); - } - } - } - - // Don't forget the last field - if let Some((name, typ)) = parse_single_field(¤t_field) { - fields.push((name, typ)); - } - - fields -} - -/// Parses a single field definition like "name: String.t()" or "count: integer()". -/// -/// # Arguments -/// * `field_str` - A single field definition string -/// -/// # Returns -/// `Some((field_name, field_type))` if parsing succeeds, `None` otherwise -fn parse_single_field(field_str: &str) -> Option<(String, String)> { - let trimmed = field_str.trim(); - if trimmed.is_empty() { - return None; - } - - // Find the first colon that separates field name from type - let colon_pos = trimmed.find(':')?; - let name = trimmed[..colon_pos].trim().to_string(); - let typ = trimmed[colon_pos + 1..].trim().to_string(); - - if name.is_empty() || typ.is_empty() { - return None; - } - - Some((name, typ)) -} - -#[cfg(test)] -mod tests { - use super::*; - - // Type formatting tests - #[test] - fn test_format_simple_struct_type() { - let input = "@type t() :: %{__struct__: MyApp.User, name: String.t(), age: integer()}"; - let result = format_type_definition(input); - - assert!(result.contains("%MyApp.User{")); - assert!(result.contains("name: String.t()")); - assert!(result.contains("age: integer()")); - } - - #[test] - fn test_format_struct_with_nested_types() { - let input = "@type t() :: %{__struct__: TradeGym.DataImporter, executions: list(), open_positions: list(), reason: String.t() | nil, status: :ok | :error}"; - let result = format_type_definition(input); - - assert!(result.contains("%TradeGym.DataImporter{")); - assert!(result.contains("executions: list()")); - assert!(result.contains("open_positions: list()")); - assert!(result.contains("reason: String.t() | nil")); - assert!(result.contains("status: :ok | :error")); - } - - #[test] - fn test_format_empty_struct() { - let input = "@type t() :: %{__struct__: MyApp.Empty}"; - let result = format_type_definition(input); - - // Empty struct should remain compact - assert!(result.contains("%MyApp.Empty{}")); - } - - #[test] - fn test_non_struct_type_unchanged() { - let input = "@type user_id() :: integer()"; - let result = format_type_definition(input); - - assert_eq!(result, input); - } - - #[test] - fn test_map_type_unchanged() { - let input = "@type options() :: %{name: String.t(), age: integer()}"; - let result = format_type_definition(input); - - // Regular maps (without __struct__) should remain unchanged - assert_eq!(result, input); - } - - #[test] - fn test_format_struct_with_complex_types() { - let input = "@type t() :: %{__struct__: MyApp.State, callbacks: list({atom(), function()}), data: map()}"; - let result = format_type_definition(input); - - assert!(result.contains("%MyApp.State{")); - assert!(result.contains("callbacks: list({atom(), function()})")); - assert!(result.contains("data: map()")); - } - - #[test] - fn test_parse_type_fields_simple() { - let input = "name: String.t(), age: integer()"; - let fields = parse_type_fields(input); - - assert_eq!(fields.len(), 2); - assert_eq!(fields[0], ("name".to_string(), "String.t()".to_string())); - assert_eq!(fields[1], ("age".to_string(), "integer()".to_string())); - } - - #[test] - fn test_parse_type_fields_with_nested_parens() { - let input = "list: list(integer()), map: map()"; - let fields = parse_type_fields(input); - - assert_eq!(fields.len(), 2); - assert_eq!(fields[0], ("list".to_string(), "list(integer())".to_string())); - assert_eq!(fields[1], ("map".to_string(), "map()".to_string())); - } - - #[test] - fn test_parse_type_fields_with_union_types() { - let input = "status: :ok | :error, reason: String.t() | nil"; - let fields = parse_type_fields(input); - - assert_eq!(fields.len(), 2); - assert_eq!(fields[0], ("status".to_string(), ":ok | :error".to_string())); - assert_eq!(fields[1], ("reason".to_string(), "String.t() | nil".to_string())); - } - - #[test] - fn test_opaque_type_unchanged() { - let input = "@opaque state() :: %{internal: map()}"; - let result = format_type_definition(input); - - assert_eq!(result, input); - } - - #[test] - fn test_typep_with_struct() { - let input = "@typep t() :: %{__struct__: MyApp.Internal, data: term()}"; - let result = format_type_definition(input); - - assert!(result.contains("%MyApp.Internal{")); - assert!(result.contains("data: term()")); - } - - // Grouping tests - #[test] - fn test_group_by_module_empty() { - let items: Vec<(String, i32)> = vec![]; - let result = group_by_module(items, |(module, item)| (module, item)); - assert_eq!(result.len(), 0); - } - - #[test] - fn test_group_by_module_single_module() { - let items = vec![ - ("math".to_string(), 1), - ("math".to_string(), 2), - ("math".to_string(), 3), - ]; - let result = group_by_module(items, |(module, item)| (module, item)); - assert_eq!(result.len(), 1); - assert_eq!(result[0].name, "math"); - assert_eq!(result[0].entries.len(), 3); - } - - #[test] - fn test_group_by_module_multiple_modules() { - let items = vec![ - ("math".to_string(), 1), - ("string".to_string(), 2), - ("math".to_string(), 3), - ("list".to_string(), 4), - ("string".to_string(), 5), - ]; - let result = group_by_module(items, |(module, item)| (module, item)); - assert_eq!(result.len(), 3); - // Verify sorted order (BTreeMap sorts) - assert_eq!(result[0].name, "list"); - assert_eq!(result[1].name, "math"); - assert_eq!(result[2].name, "string"); - // Verify items are grouped correctly - assert_eq!(result[1].entries.len(), 2); // math has 2 items - assert_eq!(result[2].entries.len(), 2); // string has 2 items - } - - #[test] - fn test_condition_builder_exact_match() { - let builder = ConditionBuilder::new("module", "module_pattern"); - assert_eq!(builder.build(false), "module == $module_pattern"); - } - - #[test] - fn test_condition_builder_regex_match() { - let builder = ConditionBuilder::new("module", "module_pattern"); - assert_eq!(builder.build(true), "regex_matches(module, $module_pattern)"); - } - - #[test] - fn test_condition_builder_with_leading_comma() { - let builder = ConditionBuilder::new("module", "module_pattern").with_leading_comma(); - assert_eq!(builder.build(false), ", module == $module_pattern"); - assert_eq!(builder.build(true), ", regex_matches(module, $module_pattern)"); - } - - #[test] - fn test_optional_condition_builder_with_value() { - let builder = OptionalConditionBuilder::new("arity", "arity"); - assert_eq!(builder.build(true), "arity == $arity"); - } - - #[test] - fn test_optional_condition_builder_without_value() { - let builder = OptionalConditionBuilder::new("arity", "arity"); - assert_eq!(builder.build(false), ""); - } - - #[test] - fn test_optional_condition_builder_with_default() { - let builder = OptionalConditionBuilder::new("arity", "arity").when_none("true"); - assert_eq!(builder.build(false), "true"); - } - - #[test] - fn test_optional_condition_builder_with_leading_comma() { - let builder = OptionalConditionBuilder::new("arity", "arity") - .with_leading_comma() - .when_none("true"); - assert_eq!(builder.build(true), ", arity == $arity"); - assert_eq!(builder.build(false), ", true"); - } -}