Skip to content

Commit

Permalink
feat(tree-sitter): Add support for Java 22 (#309)
Browse files Browse the repository at this point in the history
Co-authored-by: Timon Vonk <[email protected]>
  • Loading branch information
devsprint and timonv authored Sep 24, 2024
1 parent 1f46b24 commit fd110c8
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ tmp
.env*.local

**/.fastembed_cache
.idea/
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions swiftide-integrations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ tree-sitter-python = { version = "0.23", optional = true }
tree-sitter-ruby = { version = "0.23", optional = true }
tree-sitter-typescript = { version = "0.23", optional = true }
tree-sitter-javascript = { version = "0.23", optional = true }
tree-sitter-java = { version = "0.23", optional = true }
fastembed = { version = "4.0", optional = true }
spider = { workspace = true, optional = true }
htmd = { version = "0.1", optional = true }
Expand Down Expand Up @@ -110,6 +111,7 @@ tree-sitter = [
"dep:tree-sitter-ruby",
"dep:tree-sitter-typescript",
"dep:tree-sitter-javascript",
"dep:tree-sitter-java",
]
# OpenAI for embedding and prompting
openai = ["dep:async-openai"]
Expand Down
53 changes: 51 additions & 2 deletions swiftide-integrations/src/treesitter/code_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tree_sitter::{Parser, Query, QueryCursor, Tree};
use anyhow::{Context as _, Result};
use std::collections::HashSet;

use crate::treesitter::queries::{javascript, python, ruby, rust, typescript};
use crate::treesitter::queries::{java, javascript, python, ruby, rust, typescript};

use super::SupportedLanguages;

Expand Down Expand Up @@ -107,7 +107,7 @@ impl CodeTree<'_> {
}

fn ts_queries_for_language(language: SupportedLanguages) -> (&'static str, &'static str) {
use SupportedLanguages::{Javascript, Python, Ruby, Rust, Typescript};
use SupportedLanguages::{Java, Javascript, Python, Ruby, Rust, Typescript};

match language {
Rust => (rust::DEFS, rust::REFS),
Expand All @@ -116,6 +116,7 @@ fn ts_queries_for_language(language: SupportedLanguages) -> (&'static str, &'sta
Typescript => (typescript::DEFS, typescript::REFS),
Javascript => (javascript::DEFS, javascript::REFS),
Ruby => (ruby::DEFS, ruby::REFS),
Java => (java::DEFS, java::REFS),
}
}

Expand Down Expand Up @@ -231,4 +232,52 @@ mod tests {
assert_eq!(result.definitions, vec!["MyClass", "Test", "myMethod"]);
assert_eq!(result.references, vec!["log", "otherThing"]);
}

#[test]
fn test_parsing_on_java() {
let parser = CodeParser::from_language(SupportedLanguages::Java);
let code = r#"
public class Hello {
public static void main(String[] args) {
System.out.printf("Hello %s!%n", args[0]);
}
}
"#;
let tree = parser.parse(code).unwrap();
let result = tree.references_and_definitions().unwrap();
assert_eq!(result.definitions, vec!["Hello", "main"]);
assert_eq!(result.references, vec!["printf"]);
}

#[test]
fn test_parsing_on_java_enum() {
let parser = CodeParser::from_language(SupportedLanguages::Java);
let code = r#"
enum Material {
DENIM,
CANVAS,
SPANDEX_3_PERCENT
}
class Person {
Person(string name) {
this.name = name;
this.pants = new Pants<Pocket>();
}
String getName() {
a = this.name;
b = new one.two.Three();
c = Material.DENIM;
}
}
"#;
let tree = parser.parse(code).unwrap();
let result = tree.references_and_definitions().unwrap();
assert_eq!(result.definitions, vec!["Material", "Person", "getName"]);
assert!(result.references.is_empty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ mod test {
#[test_case("python", "def main(): print('Hello, World!')", "print", "main"; "python")]
#[test_case("javascript", "function main() { console.log('Hello, World!'); }", "log", "main"; "javascript")]
#[test_case("typescript", "function main() { console.log('Hello, World!'); }", "log", "main"; "typescript")]
#[test_case("java", "public class Main { public static void main(String[] args) { System.out.println(\"Hello, World!\"); } }", "println", "Main,main"; "java")]
#[tokio::test]
async fn assert_refs_defs_from_code(
lang: &str,
Expand Down
26 changes: 25 additions & 1 deletion swiftide-integrations/src/treesitter/outliner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl CodeOutliner {

fn is_unneeded_node(&self, node: Node) -> bool {
match self.language {
SupportedLanguages::Rust => matches!(node.kind(), "block"),
SupportedLanguages::Rust | SupportedLanguages::Java => matches!(node.kind(), "block"),
SupportedLanguages::Typescript | SupportedLanguages::Javascript => {
matches!(node.kind(), "statement_block")
}
Expand Down Expand Up @@ -298,4 +298,28 @@ class Bla {
"\nimport { Context as _, Result } from 'anyhow';\n// This is a comment\nfunction main(a, b) \n\nclass Bla {\n constructor() \n\n ok() \n}"
);
}

#[test]
fn test_outline_java() {
let code = r#"
import java.io.PrintStream;
import java.util.Scanner;
public class HelloWorld {
// This is a comment
public static void main(String[] args) {
PrintStream out = System.out;
out.println("Hello, World!");
}
}
"#;
let outliner = CodeOutliner::new(SupportedLanguages::Java);
let summary = outliner.outline(code).unwrap();
println!("{}", summary);
assert_eq!(
summary,
"\nimport java.io.PrintStream;\nimport java.util.Scanner;\n\npublic class HelloWorld {\n // This is a comment\n public static void main(String[] args) \n}"
);
}
}
28 changes: 28 additions & 0 deletions swiftide-integrations/src/treesitter/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,31 @@ pub mod rust {
macro: (identifier) @name)
";
}

// https://github.com/tree-sitter/tree-sitter-java/blob/master/queries/tags.scm
pub mod java {
pub const DEFS: &str = "
(class_declaration
name: (identifier) @name)
(enum_declaration
name: (identifier) @name)
(method_declaration
name: (identifier) @name)
(interface_declaration
name: (identifier) @name)
(type_list
(type_identifier) @name)
(superclass (type_identifier) @name)";
pub const REFS: &str = "
(method_invocation
name: (identifier) @name
arguments: (argument_list))
(object_creation_expression
type: (type_identifier) @name)";
}
16 changes: 16 additions & 0 deletions swiftide-integrations/src/treesitter/supported_languages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub enum SupportedLanguages {
Ruby,
#[serde(alias = "javascript")]
Javascript,
#[serde(alias = "java")]
Java,
}

/// Static array of file extensions for Rust files.
Expand All @@ -61,6 +63,9 @@ static RUBY_EXTENSIONS: &[&str] = &["rb"];
/// Static array of file extensions for Javascript files.
static JAVASCRIPT_EXTENSIONS: &[&str] = &["js", "jsx"];

/// Static array of file extensions for Java files.
static JAVA_EXTENSIONS: &[&str] = &["java"];

impl SupportedLanguages {
/// Returns the file extensions associated with the supported language.
///
Expand All @@ -73,6 +78,7 @@ impl SupportedLanguages {
SupportedLanguages::Python => PYTHON_EXTENSIONS,
SupportedLanguages::Ruby => RUBY_EXTENSIONS,
SupportedLanguages::Javascript => JAVASCRIPT_EXTENSIONS,
SupportedLanguages::Java => JAVA_EXTENSIONS,
}
}
}
Expand All @@ -95,6 +101,7 @@ impl From<SupportedLanguages> for tree_sitter::Language {
SupportedLanguages::Typescript => tree_sitter_typescript::LANGUAGE_TYPESCRIPT,
SupportedLanguages::Javascript => tree_sitter_javascript::LANGUAGE,
SupportedLanguages::Ruby => tree_sitter_ruby::LANGUAGE,
SupportedLanguages::Java => tree_sitter_java::LANGUAGE,
}
.into()
}
Expand All @@ -116,6 +123,10 @@ mod test {
SupportedLanguages::from_str("typescript"),
Ok(SupportedLanguages::Typescript)
);
assert_eq!(
SupportedLanguages::from_str("java"),
Ok(SupportedLanguages::Java)
);
}

/// Tests the case-insensitive string conversion for `SupportedLanguages` with different casing.
Expand All @@ -129,6 +140,11 @@ mod test {
SupportedLanguages::from_str("TypeScript"),
Ok(SupportedLanguages::Typescript)
);

assert_eq!(
SupportedLanguages::from_str("Java"),
Ok(SupportedLanguages::Java)
);
}

#[test]
Expand Down

0 comments on commit fd110c8

Please sign in to comment.