feat(bindings): add Java bindings
This commit is contained in:
parent
8ca17d1bb1
commit
b9c2d1dc89
9 changed files with 369 additions and 22 deletions
|
|
@ -36,6 +36,8 @@ const PARSER_CLASS_NAME_PLACEHOLDER: &str = "PARSER_CLASS_NAME";
|
|||
|
||||
const PARSER_DESCRIPTION_PLACEHOLDER: &str = "PARSER_DESCRIPTION";
|
||||
const PARSER_LICENSE_PLACEHOLDER: &str = "PARSER_LICENSE";
|
||||
const PARSER_NS_PLACEHOLDER: &str = "PARSER_NS";
|
||||
const PARSER_NS_CLEANED_PLACEHOLDER: &str = "PARSER_NS_CLEANED";
|
||||
const PARSER_URL_PLACEHOLDER: &str = "PARSER_URL";
|
||||
const PARSER_URL_STRIPPED_PLACEHOLDER: &str = "PARSER_URL_STRIPPED";
|
||||
const PARSER_VERSION_PLACEHOLDER: &str = "PARSER_VERSION";
|
||||
|
|
@ -58,6 +60,11 @@ const AUTHOR_BLOCK_RS: &str = "\nauthors = [";
|
|||
const AUTHOR_NAME_PLACEHOLDER_RS: &str = "PARSER_AUTHOR_NAME";
|
||||
const AUTHOR_EMAIL_PLACEHOLDER_RS: &str = " PARSER_AUTHOR_EMAIL";
|
||||
|
||||
const AUTHOR_BLOCK_JAVA: &str = "\n <developer>";
|
||||
const AUTHOR_NAME_PLACEHOLDER_JAVA: &str = "\n <name>PARSER_AUTHOR_NAME</name>";
|
||||
const AUTHOR_EMAIL_PLACEHOLDER_JAVA: &str = "\n <email>PARSER_AUTHOR_EMAIL</email>";
|
||||
const AUTHOR_URL_PLACEHOLDER_JAVA: &str = "\n <url>PARSER_AUTHOR_URL</url>";
|
||||
|
||||
const AUTHOR_BLOCK_GRAMMAR: &str = "\n * @author ";
|
||||
const AUTHOR_NAME_PLACEHOLDER_GRAMMAR: &str = "PARSER_AUTHOR_NAME";
|
||||
const AUTHOR_EMAIL_PLACEHOLDER_GRAMMAR: &str = " PARSER_AUTHOR_EMAIL";
|
||||
|
|
@ -107,6 +114,10 @@ const TEST_BINDING_PY_TEMPLATE: &str = include_str!("./templates/test_binding.py
|
|||
const PACKAGE_SWIFT_TEMPLATE: &str = include_str!("./templates/package.swift");
|
||||
const TESTS_SWIFT_TEMPLATE: &str = include_str!("./templates/tests.swift");
|
||||
|
||||
const POM_XML_TEMPLATE: &str = include_str!("./templates/pom.xml");
|
||||
const BINDING_JAVA_TEMPLATE: &str = include_str!("./templates/binding.java");
|
||||
const TEST_JAVA_TEMPLATE: &str = include_str!("./templates/test.java");
|
||||
|
||||
const BUILD_ZIG_TEMPLATE: &str = include_str!("./templates/build.zig");
|
||||
const BUILD_ZIG_ZON_TEMPLATE: &str = include_str!("./templates/build.zig.zon");
|
||||
const ROOT_ZIG_TEMPLATE: &str = include_str!("./templates/root.zig");
|
||||
|
|
@ -134,6 +145,7 @@ pub struct JsonConfigOpts {
|
|||
pub email: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub url: Option<String>,
|
||||
pub namespace: Option<String>,
|
||||
pub bindings: Bindings,
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +186,7 @@ impl JsonConfigOpts {
|
|||
}),
|
||||
funding: self.funding,
|
||||
}),
|
||||
namespace: None,
|
||||
namespace: self.namespace,
|
||||
},
|
||||
bindings: self.bindings,
|
||||
}
|
||||
|
|
@ -197,6 +209,7 @@ impl Default for JsonConfigOpts {
|
|||
author: String::new(),
|
||||
email: None,
|
||||
url: None,
|
||||
namespace: None,
|
||||
bindings: Bindings::default(),
|
||||
}
|
||||
}
|
||||
|
|
@ -218,6 +231,7 @@ struct GenerateOpts<'a> {
|
|||
injections_query_path: &'a str,
|
||||
locals_query_path: &'a str,
|
||||
tags_query_path: &'a str,
|
||||
namespace: Option<&'a str>,
|
||||
}
|
||||
|
||||
pub fn generate_grammar_files(
|
||||
|
|
@ -311,6 +325,7 @@ pub fn generate_grammar_files(
|
|||
tags_query_path: tree_sitter_config.grammars[0]
|
||||
.tags
|
||||
.to_variable_value(&default_tags_path),
|
||||
namespace: tree_sitter_config.metadata.namespace.as_deref(),
|
||||
};
|
||||
|
||||
// Create package.json
|
||||
|
|
@ -1048,6 +1063,45 @@ pub fn generate_grammar_files(
|
|||
})?;
|
||||
}
|
||||
|
||||
// Generate Java bindings
|
||||
if tree_sitter_config.bindings.java {
|
||||
missing_path(repo_path.join("pom.xml"), |path| {
|
||||
generate_file(path, POM_XML_TEMPLATE, language_name, &generate_opts)
|
||||
})?;
|
||||
|
||||
missing_path(bindings_dir.join("java"), create_dir)?.apply(|path| {
|
||||
missing_path(path.join("main"), create_dir)?.apply(|path| {
|
||||
let package_path = generate_opts
|
||||
.namespace
|
||||
.unwrap_or("io.github.treesitter")
|
||||
.replace(['-', '_'], "")
|
||||
.split('.')
|
||||
.fold(path.to_path_buf(), |path, dir| path.join(dir))
|
||||
.join("jtreesitter")
|
||||
.join(language_name.to_lowercase().replace('_', ""));
|
||||
missing_path(package_path, create_dir)?.apply(|path| {
|
||||
missing_path(path.join(format!("{class_name}.java")), |path| {
|
||||
generate_file(path, BINDING_JAVA_TEMPLATE, language_name, &generate_opts)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
missing_path(path.join("test"), create_dir)?.apply(|path| {
|
||||
missing_path(path.join(format!("{class_name}Test.java")), |path| {
|
||||
generate_file(path, TEST_JAVA_TEMPLATE, language_name, &generate_opts)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1097,6 +1151,15 @@ fn generate_file(
|
|||
) -> Result<()> {
|
||||
let filename = path.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let lower_parser_name = if path
|
||||
.extension()
|
||||
.is_some_and(|e| e.eq_ignore_ascii_case("java"))
|
||||
{
|
||||
language_name.to_snake_case().replace('_', "")
|
||||
} else {
|
||||
language_name.to_snake_case()
|
||||
};
|
||||
|
||||
let mut replacement = template
|
||||
.replace(
|
||||
CAMEL_PARSER_NAME_PLACEHOLDER,
|
||||
|
|
@ -1110,14 +1173,11 @@ fn generate_file(
|
|||
UPPER_PARSER_NAME_PLACEHOLDER,
|
||||
&language_name.to_shouty_snake_case(),
|
||||
)
|
||||
.replace(
|
||||
LOWER_PARSER_NAME_PLACEHOLDER,
|
||||
&language_name.to_snake_case(),
|
||||
)
|
||||
.replace(
|
||||
KEBAB_PARSER_NAME_PLACEHOLDER,
|
||||
&language_name.to_kebab_case(),
|
||||
)
|
||||
.replace(LOWER_PARSER_NAME_PLACEHOLDER, &lower_parser_name)
|
||||
.replace(PARSER_NAME_PLACEHOLDER, language_name)
|
||||
.replace(CLI_VERSION_PLACEHOLDER, CLI_VERSION)
|
||||
.replace(RUST_BINDING_VERSION_PLACEHOLDER, RUST_BINDING_VERSION)
|
||||
|
|
@ -1157,6 +1217,9 @@ fn generate_file(
|
|||
"Cargo.toml" => {
|
||||
replacement = replacement.replace(AUTHOR_NAME_PLACEHOLDER_RS, "");
|
||||
}
|
||||
"pom.xml" => {
|
||||
replacement = replacement.replace(AUTHOR_NAME_PLACEHOLDER_JAVA, "");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1182,30 +1245,52 @@ fn generate_file(
|
|||
"Cargo.toml" => {
|
||||
replacement = replacement.replace(AUTHOR_EMAIL_PLACEHOLDER_RS, "");
|
||||
}
|
||||
"pom.xml" => {
|
||||
replacement = replacement.replace(AUTHOR_EMAIL_PLACEHOLDER_JAVA, "");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if filename == "package.json" {
|
||||
if let Some(url) = generate_opts.author_url {
|
||||
match (generate_opts.author_url, filename) {
|
||||
(Some(url), "package.json" | "pom.xml") => {
|
||||
replacement = replacement.replace(AUTHOR_URL_PLACEHOLDER, url);
|
||||
} else {
|
||||
}
|
||||
(None, "package.json") => {
|
||||
replacement = replacement.replace(AUTHOR_URL_PLACEHOLDER_JS, "");
|
||||
}
|
||||
(None, "pom.xml") => {
|
||||
replacement = replacement.replace(AUTHOR_URL_PLACEHOLDER_JAVA, "");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if generate_opts.author_name.is_none()
|
||||
&& generate_opts.author_email.is_none()
|
||||
&& generate_opts.author_url.is_none()
|
||||
&& filename == "package.json"
|
||||
{
|
||||
if let Some(start_idx) = replacement.find(AUTHOR_BLOCK_JS) {
|
||||
if let Some(end_idx) = replacement[start_idx..]
|
||||
.find("},")
|
||||
.map(|i| i + start_idx + 2)
|
||||
{
|
||||
replacement.replace_range(start_idx..end_idx, "");
|
||||
match filename {
|
||||
"package.json" => {
|
||||
if let Some(start_idx) = replacement.find(AUTHOR_BLOCK_JS) {
|
||||
if let Some(end_idx) = replacement[start_idx..]
|
||||
.find("},")
|
||||
.map(|i| i + start_idx + 2)
|
||||
{
|
||||
replacement.replace_range(start_idx..end_idx, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
"pom.xml" => {
|
||||
if let Some(start_idx) = replacement.find(AUTHOR_BLOCK_JAVA) {
|
||||
if let Some(end_idx) = replacement[start_idx..]
|
||||
.find("</developer>")
|
||||
.map(|i| i + start_idx + 12)
|
||||
{
|
||||
replacement.replace_range(start_idx..end_idx, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if generate_opts.author_name.is_none() && generate_opts.author_email.is_none() {
|
||||
match filename {
|
||||
|
|
@ -1286,6 +1371,19 @@ fn generate_file(
|
|||
);
|
||||
}
|
||||
|
||||
if let Some(namespace) = generate_opts.namespace {
|
||||
replacement = replacement
|
||||
.replace(
|
||||
PARSER_NS_CLEANED_PLACEHOLDER,
|
||||
&namespace.replace(['-', '_'], ""),
|
||||
)
|
||||
.replace(PARSER_NS_PLACEHOLDER, namespace);
|
||||
} else {
|
||||
replacement = replacement
|
||||
.replace(PARSER_NS_CLEANED_PLACEHOLDER, "io.github.treesitter")
|
||||
.replace(PARSER_NS_PLACEHOLDER, "io.github.tree-sitter");
|
||||
}
|
||||
|
||||
if let Some(funding_url) = generate_opts.funding {
|
||||
match filename {
|
||||
"pyproject.toml" | "package.json" => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue