From 5a52d1d872ee022215140aa7a1616700acf2f6e5 Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Mon, 24 Jun 2024 10:51:59 +0300 Subject: [PATCH] feat: add java bindings --- .editorconfig | 2 +- bindings/java/pom.xml | 175 ++++++++++++++++++ .../jtreesitter/java/TreeSitterJava.java | 45 +++++ .../src/test/java/TreeSitterJavaTest.java | 12 ++ 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 bindings/java/pom.xml create mode 100644 bindings/java/src/main/java/io/github/treesitter/jtreesitter/java/TreeSitterJava.java create mode 100644 bindings/java/src/test/java/TreeSitterJavaTest.java diff --git a/.editorconfig b/.editorconfig index d3a8b5b..e58a185 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true -[*.{json,toml,yml,gyp}] +[*.{json,toml,yml,gyp,xml}] indent_style = space indent_size = 2 diff --git a/bindings/java/pom.xml b/bindings/java/pom.xml new file mode 100644 index 0000000..d84821f --- /dev/null +++ b/bindings/java/pom.xml @@ -0,0 +1,175 @@ + + + 4.0.0 + io.github.tree-sitter + jtreesitter-java + JTreeSitter Java + 0.23.2 + Java grammar for JTreeSitter + https://github.com/tree-sitter/tree-sitter-java + + tree-sitter + https://github.com/tree-sitter + + + + MIT + https://spdx.org/licenses/MIT.html + + + + + Ayman Nadeem + aymannadeem@github.com + https://github.com/aymannadeem + + + Max Brunsfeld + maxbrunsfeld@gmail.com + https://github.com/maxbrunsfeld + + + Amaan Qureshi + amaanq12@gmail.com + https://github.com/amaanq + + + + https://github.com/tree-sitter/tree-sitter-java + scm:git:git://github.com/tree-sitter/tree-sitter-java.git + scm:git:ssh://github.com/tree-sitter/tree-sitter-java.git + + + Github Actions + https://github.com/tree-sitter/tree-sitter-java/actions + + + GitHub Issues + https://github.com/tree-sitter/tree-sitter-java/issues + + + 22 + 22 + UTF-8 + true + true + false + true + + + + io.github.tree-sitter + jtreesitter + 0.23.0 + test + + + org.junit.jupiter + junit-jupiter-api + 5.11.0 + test + + + + + + maven-surefire-plugin + 3.2.5 + + + ${project.build.directory}/reports/surefire + + --enable-native-access=ALL-UNNAMED + + + + maven-javadoc-plugin + 3.8.0 + + + + jar + + + + + public + true + true + all,-missing + + + + maven-source-plugin + 3.3.1 + + + + jar-no-fork + + + + + + maven-gpg-plugin + 3.2.5 + + + verify + + sign + + + true + + --no-tty + --pinentry-mode + loopback + + + + + + + org.sonatype.central + central-publishing-maven-plugin + 0.5.0 + + + deploy + + publish + + + validated + ${publish.auto} + ${publish.skip} + ${project.artifactId}-${project.version}.zip + ${project.artifactId}-${project.version}.zip + + + + true + + + + + + ci + + + env.CI + true + + + + false + true + false + + + + diff --git a/bindings/java/src/main/java/io/github/treesitter/jtreesitter/java/TreeSitterJava.java b/bindings/java/src/main/java/io/github/treesitter/jtreesitter/java/TreeSitterJava.java new file mode 100644 index 0000000..9e5d3ca --- /dev/null +++ b/bindings/java/src/main/java/io/github/treesitter/jtreesitter/java/TreeSitterJava.java @@ -0,0 +1,45 @@ +package io.github.treesitter.jtreesitter.java; + +import java.lang.foreign.*; +import java.lang.invoke.MethodHandle; + +/** Java grammar for tree-sitter */ +public final class TreeSitterJava { + private static final ValueLayout VOID_PTR = + ValueLayout.ADDRESS.withTargetLayout(MemoryLayout.sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE)); + private static final FunctionDescriptor FUNC_DESC = FunctionDescriptor.of(VOID_PTR); + private static final Linker LINKER = Linker.nativeLinker(); + private static final TreeSitterJava INSTANCE = new TreeSitterJava(); + + private final Arena arena = Arena.ofAuto(); + private final SymbolLookup symbols = findLibrary(); + + /** Get the tree-sitter {@code Language} for this grammar */ + public static MemorySegment language() { + return INSTANCE.call("tree_sitter_java"); + } + + private SymbolLookup findLibrary() { + try { + var library = System.mapLibraryName("tree-sitter-java"); + return SymbolLookup.libraryLookup(library, arena); + } catch (IllegalArgumentException e) { + return SymbolLookup.loaderLookup(); + } + } + + private static UnsatisfiedLinkError unresolved(String name) { + return new UnsatisfiedLinkError("Unresolved symbol: %s".formatted(name)); + } + + @SuppressWarnings("SameParameterValue") + private MemorySegment call(String name) throws UnsatisfiedLinkError { + var address = symbols.find(name).orElseThrow(() -> unresolved(name)); + try { + final MethodHandle function = LINKER.downcallHandle(address, FUNC_DESC); + return ((MemorySegment) function.invokeExact()).asReadOnly(); + } catch (Throwable e) { + throw new RuntimeException("Call to %s failed".formatted(name), e); + } + } +} diff --git a/bindings/java/src/test/java/TreeSitterJavaTest.java b/bindings/java/src/test/java/TreeSitterJavaTest.java new file mode 100644 index 0000000..45dd5cc --- /dev/null +++ b/bindings/java/src/test/java/TreeSitterJavaTest.java @@ -0,0 +1,12 @@ +import io.github.treesitter.jtreesitter.Language; +import io.github.treesitter.jtreesitter.java.TreeSitterJava; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +public class TreeSitterJavaTest { + @Test + public void testCanLoadLanguage() { + assertDoesNotThrow(() -> new Language(TreeSitterJava.language())); + } +}