Current section

Files

Jump to
cleam src internal ast.gleam
Raw

src/internal/ast.gleam

import gleam/list
import internal/fs.{FileContent, FilesDir, ModuleFullName}
import glance.{
type Module as AST, Definition, Function, Import, Module as AST,
UnqualifiedImport,
}
import gleam/option.{None, Some}
import gleam/string
pub type FileAst {
FileAst(AST)
}
pub type AnotherFilesAst {
AnotherFilesAst(List(FileAst))
}
pub type ModuleName {
ModuleName(String)
}
type ImportedInfo {
ModuleImported(ModuleName)
ImportedAsAlias
}
pub type PublicMember {
PublicFun(String)
PublicConst(String)
PublicType(String)
}
pub fn files_ast(files_contents) {
use content <- list.map(files_contents)
let assert FileContent(content) = content
let assert Ok(ast) = glance.module(content)
FileAst(ast)
}
pub fn files_paths_with_ast(dir, test_dir) {
let file_paths = fs.files_paths(dir)
let flle_contents = fs.files_contents(file_paths)
let test_file_contents = case test_dir {
Some(FilesDir(_) as test_dir) -> {
fs.files_paths(test_dir)
|> fs.files_contents
}
None -> []
}
let ast_list =
flle_contents
|> list.append(test_file_contents)
|> files_ast
let indexes = list.range(0, list.length(ast_list) - 1)
use index <- list.filter_map(indexes)
case list.at(file_paths, index) {
Ok(file_path) -> {
let assert Ok(file_ast) = list.at(ast_list, index)
Ok(#(
file_path,
file_ast,
AnotherFilesAst(
list.filter_map(indexes, fn(idx) {
case idx == index {
True -> Error(Nil)
False -> list.at(ast_list, idx)
}
}),
),
))
}
Error(Nil) -> Error(Nil)
}
}
fn imported_info(imports, module_full_name, exported) {
list.filter_map(imports, fn(imp) {
case imp {
Definition(_, Import(import_name, module_alias, type_aliases, aliases))
if ModuleFullName(import_name) == module_full_name
->
case
aliases
|> list.append(type_aliases)
|> list.any(fn(alias) {
let assert UnqualifiedImport(imported, _) = alias
PublicFun(imported) == exported
|| PublicConst(imported) == exported
|| PublicType(imported) == exported
})
{
True -> Ok(ImportedAsAlias)
False ->
Ok(
ModuleImported(case module_alias {
Some(alias) -> ModuleName(alias)
None -> module_full_name_to_module_name(module_full_name)
}),
)
}
_ -> Error(Nil)
}
})
}
pub fn is_pub_member_used(
files_ast,
pub_member_name,
module_full_name,
check_usage,
) {
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 =
imported_info(imports, module_full_name, pub_member_name)
use imported_info <- list.find_map(imported_info_list)
case imported_info {
ImportedAsAlias -> Ok(Nil)
ModuleImported(module_name) -> {
use fun_def <- list.find_map(fns)
let assert Definition(_, Function(_, _, _, _, statements, _)) = fun_def
check_usage(statements, pub_member_name, module_name)
}
}
}
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)
}