Skip to content

Commit

Permalink
1st attempt to add support for elixir
Browse files Browse the repository at this point in the history
  • Loading branch information
setop committed Dec 30, 2024
1 parent 50b976d commit 966911b
Show file tree
Hide file tree
Showing 109 changed files with 482,880 additions and 0 deletions.
28 changes: 28 additions & 0 deletions crates/core/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14790,6 +14790,34 @@ fn yaml_indents_join() {
.unwrap();
}

#[test]
fn elixir_hello_world() {
run_test_expected({
TestArgExpected {
pattern: r#"
|language elixir
|
|`IO.puts ^string` => `IO.puts ^string <> " modified"`
|"#
.trim_margin()
.unwrap(),
source: r#"
|IO.puts "hello world"
|IO.puts "hello again"
|"#
.trim_margin()
.unwrap(),
expected: r#"
|IO.puts "hello world" <> " modified"
|IO.puts "hello again" <> " modified"
|"#
.trim_margin()
.unwrap(),
}
})
.unwrap();
}

#[test]
fn ruby_hello_world() {
run_test_expected({
Expand Down
6 changes: 6 additions & 0 deletions crates/gritmodule/src/patterns_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct PatternsDirectory {
go: BTreeMap<String, String>,
rust: BTreeMap<String, String>,
ruby: BTreeMap<String, String>,
elixir: BTreeMap<String, String>,
solidity: BTreeMap<String, String>,
hcl: BTreeMap<String, String>,
yaml: BTreeMap<String, String>,
Expand Down Expand Up @@ -76,6 +77,7 @@ impl PatternsDirectory {
go: BTreeMap::new(),
rust: BTreeMap::new(),
ruby: BTreeMap::new(),
elixir: BTreeMap::new(),
solidity: BTreeMap::new(),
hcl: BTreeMap::new(),
yaml: BTreeMap::new(),
Expand Down Expand Up @@ -107,6 +109,7 @@ impl PatternsDirectory {
PatternLanguage::Go => &mut self.go,
PatternLanguage::Rust => &mut self.rust,
PatternLanguage::Ruby => &mut self.ruby,
PatternLanguage::Elixir => &mut self.elixir,
PatternLanguage::Solidity => &mut self.solidity,
PatternLanguage::Hcl => &mut self.hcl,
PatternLanguage::Yaml => &mut self.yaml,
Expand Down Expand Up @@ -135,6 +138,7 @@ impl PatternsDirectory {
PatternLanguage::Go => &self.go,
PatternLanguage::Rust => &self.rust,
PatternLanguage::Ruby => &self.ruby,
PatternLanguage::Elixir => &self.elixir,
PatternLanguage::Solidity => &self.solidity,
PatternLanguage::Hcl => &self.hcl,
PatternLanguage::Yaml => &self.yaml,
Expand Down Expand Up @@ -256,6 +260,8 @@ impl PatternsDirectory {
self.rust = other.rust;
other.ruby.extend(mem::take(&mut self.ruby));
self.ruby = other.ruby;
other.elixir.extend(mem::take(&mut self.elixir));
self.elixir = other.elixir;
other.solidity.extend(mem::take(&mut self.solidity));
self.solidity = other.solidity;
other.hcl.extend(mem::take(&mut self.hcl));
Expand Down
2 changes: 2 additions & 0 deletions crates/language/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ tree-sitter-python = { path = "../../resources/language-metavariables/tree-sitte
tree-sitter-md = { path = "../../resources/language-metavariables/tree-sitter-markdown", optional = true }
tree-sitter-go = { path = "../../resources/language-metavariables/tree-sitter-go", optional = true }
tree-sitter-rust = { path = "../../resources/language-metavariables/tree-sitter-rust", optional = true }
tree-sitter-elixir = { path = "../../resources/language-metavariables/tree-sitter-elixir", optional = true }
tree-sitter-ruby = { path = "../../resources/language-metavariables/tree-sitter-ruby", optional = true }
tree-sitter-sql = { path = "../../resources/language-metavariables/tree-sitter-sql", optional = true }
tree-sitter-vue = { path = "../../resources/language-metavariables/tree-sitter-vue", optional = true }
Expand Down Expand Up @@ -70,6 +71,7 @@ builtin-parser = [
"tree-sitter-go",
"tree-sitter-rust",
"tree-sitter-ruby",
"tree-sitter-elixir",
"tree-sitter-sql",
"tree-sitter-vue",
"tree-sitter-toml",
Expand Down
119 changes: 119 additions & 0 deletions crates/language/src/elixir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
use crate::language::{fields_for_nodes, Field, MarzanoLanguage, NodeTypes, SortId, TSLanguage};
use grit_util::Language;
use lazy_static::lazy_static;
use marzano_util::node_with_source::NodeWithSource;
use regex::Regex;
use std::sync::OnceLock;

static NODE_TYPES_STRING: &str = include_str!("../../../resources/node-types/elixir-node-types.json");

static NODE_TYPES: OnceLock<Vec<Vec<Field>>> = OnceLock::new();
static LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();

#[cfg(not(feature = "builtin-parser"))]
fn language() -> TSLanguage {
unimplemented!(
"tree-sitter parser must be initialized before use when [builtin-parser] is off."
)
}
#[cfg(feature = "builtin-parser")]
fn language() -> TSLanguage {
tree_sitter_elixir::language().into()
}

#[derive(Debug, Clone, Copy)]
pub struct Elixir {
node_types: &'static [Vec<Field>],
metavariable_sort: SortId,
comment_sort: SortId,
language: &'static TSLanguage,
}

impl Elixir {
pub(crate) fn new(lang: Option<TSLanguage>) -> Self {
let language = LANGUAGE.get_or_init(|| lang.unwrap_or_else(language));
let node_types = NODE_TYPES.get_or_init(|| fields_for_nodes(language, NODE_TYPES_STRING));
let metavariable_sort = language.id_for_node_kind("grit_metavariable", true);
let comment_sort = language.id_for_node_kind("comment", true);
Self {
node_types,
metavariable_sort,
comment_sort,
language,
}
}
pub(crate) fn is_initialized() -> bool {
LANGUAGE.get().is_some()
}
}

impl NodeTypes for Elixir {
fn node_types(&self) -> &[Vec<Field>] {
self.node_types
}
}

lazy_static! {
static ref EXACT_VARIABLE_REGEX: Regex = Regex::new(r"^\^([A-Za-z_][A-Za-z0-9_]*)$")
.expect("Failed to compile EXACT_VARIABLE_REGEX");
static ref VARIABLE_REGEX: Regex =
Regex::new(r"\^(\.\.\.|[A-Za-z_][A-Za-z0-9_]*)").expect("Failed to compile VARIABLE_REGEX");
static ref BRACKET_VAR_REGEX: Regex =
Regex::new(r"\^\[([A-Za-z_][A-Za-z0-9_]*)\]").expect("Failed to compile BRACKET_VAR_REGEX");
}

impl Language for Elixir {
use_marzano_delegate!();

fn language_name(&self) -> &'static str {
"Elixir"
}

fn snippet_context_strings(&self) -> &[(&'static str, &'static str)] {
&[
("", ""),
("do GRIT_VARIABLE\n", "\nend"),
("case GRIT_VARIABLE\n", "\nend"),
("{", "}"),
("[", "]"),
]
}

fn comment_prefix(&self) -> &'static str {
"#"
}

fn metavariable_prefix(&self) -> &'static str {
"^"
}

fn metavariable_regex(&self) -> &'static Regex {
&VARIABLE_REGEX
}

fn metavariable_bracket_regex(&self) -> &'static Regex {
&BRACKET_VAR_REGEX
}

fn exact_variable_regex(&self) -> &'static Regex {
&EXACT_VARIABLE_REGEX
}

fn make_single_line_comment(&self, text: &str) -> String {
format!("# {}\n", text)
}
}

impl<'a> MarzanoLanguage<'a> for Elixir {
fn get_ts_language(&self) -> &TSLanguage {
self.language
}

fn is_comment_sort(&self, id: SortId) -> bool {
id == self.comment_sort
}

fn metavariable_sort(&self) -> SortId {
self.metavariable_sort
}
}
1 change: 1 addition & 0 deletions crates/language/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ mod php_like;
pub mod php_only;
pub mod python;
pub mod ruby;
pub mod elixir;
pub mod rust;
pub mod solidity;
pub mod sourcemap;
Expand Down
12 changes: 12 additions & 0 deletions crates/language/src/target_language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use crate::{
php_only::PhpOnly,
python::Python,
ruby::Ruby,
elixir::Elixir,
rust::Rust,
solidity::Solidity,
sql::Sql,
Expand Down Expand Up @@ -65,6 +66,7 @@ pub enum PatternLanguage {
Go,
Rust,
Ruby,
Elixir,
Solidity,
Hcl,
Yaml,
Expand Down Expand Up @@ -93,6 +95,7 @@ impl fmt::Display for PatternLanguage {
PatternLanguage::Go => write!(f, "go"),
PatternLanguage::Rust => write!(f, "rust"),
PatternLanguage::Ruby => write!(f, "ruby"),
PatternLanguage::Elixir => write!(f, "elixir"),
PatternLanguage::Solidity => write!(f, "solidity"),
PatternLanguage::Hcl => write!(f, "hcl"),
PatternLanguage::Yaml => write!(f, "yaml"),
Expand Down Expand Up @@ -128,6 +131,7 @@ impl ValueEnum for PatternLanguage {
Self::Go,
Self::Rust,
Self::Ruby,
Self::Elixir,
Self::Solidity,
Self::Hcl,
Self::Yaml,
Expand Down Expand Up @@ -232,6 +236,7 @@ impl PatternLanguage {
"go" => Some(Self::Go),
"rust" => Some(Self::Rust),
"ruby" => Some(Self::Ruby),
"elixir" => Some(Self::Elixir),
"sol" | "solidity" => Some(Self::Solidity),
"hcl" => Some(Self::Hcl),
"yaml" => Some(Self::Yaml),
Expand Down Expand Up @@ -293,6 +298,7 @@ impl PatternLanguage {
PatternLanguage::Go => &["go"],
PatternLanguage::Rust => &["rs"],
PatternLanguage::Ruby => &["rb"],
PatternLanguage::Elixir => &["ex", "exs"],
PatternLanguage::Solidity => &["sol"],
PatternLanguage::Hcl => &["hcl", "tf", "tfvars"],
PatternLanguage::Yaml => &["yaml", "yml"],
Expand Down Expand Up @@ -321,6 +327,7 @@ impl PatternLanguage {
PatternLanguage::Go => Some("go"),
PatternLanguage::Rust => Some("rs"),
PatternLanguage::Ruby => Some("rb"),
PatternLanguage::Elixir => Some("ex"),
PatternLanguage::Solidity => Some("sol"),
PatternLanguage::Hcl => Some("tf"),
PatternLanguage::Yaml => Some("yaml"),
Expand Down Expand Up @@ -348,6 +355,7 @@ impl PatternLanguage {
"go" => Some(Self::Go),
"rs" => Some(Self::Rust),
"rb" => Some(Self::Ruby),
"ex" | "exs" => Some(Self::Elixir),
"sol" => Some(Self::Solidity),
"hcl" | "tf" | "tfvars" => Some(Self::Hcl),
"yaml" | "yml" => Some(Self::Yaml),
Expand Down Expand Up @@ -394,6 +402,7 @@ impl PatternLanguage {
PatternLanguage::Go => Ok(TargetLanguage::Go(Go::new(Some(lang)))),
PatternLanguage::Rust => Ok(TargetLanguage::Rust(Rust::new(Some(lang)))),
PatternLanguage::Ruby => Ok(TargetLanguage::Ruby(Ruby::new(Some(lang)))),
PatternLanguage::Elixir => Ok(TargetLanguage::Elixir(Elixir::new(Some(lang)))),
PatternLanguage::Solidity => Ok(TargetLanguage::Solidity(Solidity::new(Some(lang)))),
PatternLanguage::Hcl => Ok(TargetLanguage::Hcl(Hcl::new(Some(lang)))),
PatternLanguage::Yaml => Ok(TargetLanguage::Yaml(Yaml::new(Some(lang)))),
Expand Down Expand Up @@ -748,6 +757,7 @@ generate_target_language! {
Go,
Rust,
Ruby,
Elixir,
Solidity,
Hcl,
Yaml,
Expand Down Expand Up @@ -775,6 +785,7 @@ impl fmt::Display for TargetLanguage {
TargetLanguage::Go(_) => write!(f, "go"),
TargetLanguage::Rust(_) => write!(f, "rust"),
TargetLanguage::Ruby(_) => write!(f, "ruby"),
TargetLanguage::Elixir(_) => write!(f, "elixir"),
TargetLanguage::Solidity(_) => write!(f, "solidity"),
TargetLanguage::Hcl(_) => write!(f, "hcl"),
TargetLanguage::Yaml(_) => write!(f, "yaml"),
Expand Down Expand Up @@ -827,6 +838,7 @@ impl TargetLanguage {
| TargetLanguage::TypeScript(_) => Regex::new(r"//\s*(.*)").unwrap(),
TargetLanguage::Python(_)
| TargetLanguage::Ruby(_)
| TargetLanguage::Elixir(_)
| TargetLanguage::Toml(_)
| TargetLanguage::Yaml(_) => Regex::new(r"#\s*(.*)").unwrap(),
TargetLanguage::Hcl(_) => Regex::new(r"(#|//)\s*(.*)").unwrap(),
Expand Down
2 changes: 2 additions & 0 deletions crates/lsp/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub fn language_id_to_pattern_language(language_id: &str) -> Option<PatternLangu
"go" => Some(PatternLanguage::Go),
"rust" => Some(PatternLanguage::Rust),
"ruby" => Some(PatternLanguage::Ruby),
"elixir" => Some(PatternLanguage::Elixir),
"solidity" => Some(PatternLanguage::Solidity),
"hcl" | "terraform" => Some(PatternLanguage::Hcl),
"yaml" => Some(PatternLanguage::Yaml),
Expand All @@ -41,6 +42,7 @@ pub fn target_language_to_language_id(target_language: TargetLanguage) -> &'stat
TargetLanguage::Go(_) => "go",
TargetLanguage::Rust(_) => "rust",
TargetLanguage::Ruby(_) => "ruby",
TargetLanguage::Elixir(_) => "elixir",
TargetLanguage::Solidity(_) => "solidity",
TargetLanguage::Hcl(_) => "hcl",
TargetLanguage::Yaml(_) => "yaml",
Expand Down
3 changes: 3 additions & 0 deletions crates/wasm-bindings/src/match_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static MARKDOWN_INLINE_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static GO_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static RUST_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static RUBY_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static ELIXIR_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static SOLIDITY_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static HCL_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
static YAML_LANGUAGE: OnceLock<TSLanguage> = OnceLock::new();
Expand Down Expand Up @@ -474,6 +475,7 @@ fn pattern_language_to_path(lang: &PatternLanguage) -> anyhow::Result<String> {
PatternLanguage::Go => Ok("/tree-sitter-go.wasm"),
PatternLanguage::Rust => Ok("/tree-sitter-rust.wasm"),
PatternLanguage::Ruby => Ok("/tree-sitter-ruby.wasm"),
PatternLanguage::Elixir=> Ok("/tree-sitter-elixir.wasm"),
PatternLanguage::Solidity => Ok("/tree-sitter-solidity.wasm"),
PatternLanguage::Hcl => Ok("/tree-sitter-hcl.wasm"),
PatternLanguage::Yaml => Ok("/tree-sitter-yaml.wasm"),
Expand Down Expand Up @@ -518,6 +520,7 @@ fn get_lang_store(language: &PatternLanguage) -> anyhow::Result<&'static OnceLoc
PatternLanguage::Go => Ok(&GO_LANGUAGE),
PatternLanguage::Rust => Ok(&RUST_LANGUAGE),
PatternLanguage::Ruby => Ok(&RUBY_LANGUAGE),
PatternLanguage::Elixir => Ok(&ELIXIR_LANGUAGE),
PatternLanguage::Solidity => Ok(&SOLIDITY_LANGUAGE),
PatternLanguage::Hcl => Ok(&HCL_LANGUAGE),
PatternLanguage::Yaml => Ok(&YAML_LANGUAGE),
Expand Down
12 changes: 12 additions & 0 deletions resources/language-metavariables/tree-sitter-elixir/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
AlignArrayOfStructures: Left
BasedOnStyle: LLVM
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: false
SeparateDefinitionBlocks: Always
SortIncludes: CaseInsensitive
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceBeforeCaseColon: false
Loading

0 comments on commit 966911b

Please sign in to comment.