Current section

Files

Jump to
cleam src internal ast_fun.gleam
Raw

src/internal/ast_fun.gleam

import gleam/string
import gleam/list
import glance.{
type Module as AST, Definition, Function, Import, Module as AST, Public,
UnqualifiedImport,
}
import internal/fs.{ModuleFullName}
import gleam/option.{None, Some}
import internal/ast.{AnotherFilesAst, FileAst}
const main_fun_name = "main"
pub type PublicFun {
PublicFun(String)
}
type ModuleName {
ModuleName(String)
}
type ImportedInfo {
ModuleImported(ModuleName)
FunctionImportedAsAlias
}
pub fn public_funs(file_ast) {
let assert FileAst(ast) = file_ast
let assert AST(_, _, _, _, _, _, funs) = ast
use fun_def <- list.flat_map(funs)
let assert Definition(_, Function(fun_name, is_public, ..)) = fun_def
case is_public {
Public if fun_name != main_fun_name -> [PublicFun(fun_name)]
_ -> []
}
}
pub fn is_pub_fun_used(files_ast, pub_fun_name, module_full_name) {
let is_used_somewhere = {
let assert AnotherFilesAst(files_ast) = files_ast
use file_ast <- list.find_map(files_ast)
let assert FileAst(ast) = file_ast
let assert AST(imports, _, _, _, _, _, fns) = ast
let imported_info_list =
function_imported_info(imports, module_full_name, pub_fun_name)
use imported_info <- list.find_map(imported_info_list)
case imported_info {
FunctionImportedAsAlias -> Ok(Nil)
ModuleImported(module_name) -> {
use fun_def <- list.find_map(fns)
let assert Definition(_, Function(_, _, _, _, statements, _)) = fun_def
check_fun_usage(statements, pub_fun_name, module_name)
}
}
}
case is_used_somewhere {
Ok(Nil) -> True
Error(Nil) -> False
}
}
fn check_fun_usage(statements, pub_fun_name, module_name) {
let assert PublicFun(pub_fun_name) = pub_fun_name
let assert ModuleName(module_name) = module_name
use statement <- list.find_map(statements)
case
statement
|> string.inspect
|> string.contains(
"FieldAccess(Variable(\""
<> module_name
<> "\"), \""
<> pub_fun_name
<> "\")",
)
{
True -> Ok(Nil)
False -> Error(Nil)
}
}
fn module_full_name_to_module_name(module_full_name) {
let assert ModuleFullName(module_full_name) = module_full_name
let assert Ok(module_name) =
string.split(module_full_name, "/")
|> list.last
ModuleName(module_name)
}
fn function_imported_info(imports, module_full_name, pub_fun_name) {
list.filter_map(imports, fn(imp) {
case imp {
Definition(_, Import(import_name, module_alias, _, aliases))
if ModuleFullName(import_name) == module_full_name
->
case
list.any(aliases, fn(alias) {
let assert UnqualifiedImport(fun_name, _) = alias
PublicFun(fun_name) == pub_fun_name
})
{
True -> Ok(FunctionImportedAsAlias)
False ->
Ok(
ModuleImported(case module_alias {
Some(alias) -> ModuleName(alias)
None -> module_full_name_to_module_name(module_full_name)
}),
)
}
_ -> Error(Nil)
}
})
}