From a49775059fa226c0feca906066caf8e254da93eb Mon Sep 17 00:00:00 2001 From: Ronny Chevalier Date: Fri, 2 Aug 2024 17:46:20 +0200 Subject: [PATCH] feat: add support for Kotlin --- Cargo.lock | 11 +++++++ Cargo.toml | 4 ++- README.md | 8 ++--- src/lang.rs | 3 ++ src/lang/kotlin.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 src/lang/kotlin.rs diff --git a/Cargo.lock b/Cargo.lock index b3a7013..b8102eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -695,6 +695,16 @@ dependencies = [ "tree-sitter", ] +[[package]] +name = "tree-sitter-kotlin" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4e35f3780ff02706f0cbe488b822c69d419bf69dc7d67ab4dfd8722b28771c" +dependencies = [ + "cc", + "tree-sitter", +] + [[package]] name = "tree-sitter-md" version = "0.2.3" @@ -765,6 +775,7 @@ dependencies = [ "tree-sitter-cpp", "tree-sitter-go", "tree-sitter-json", + "tree-sitter-kotlin", "tree-sitter-md", "tree-sitter-python", "tree-sitter-rust", diff --git a/Cargo.toml b/Cargo.toml index 57f3abe..fadcb77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ lang-all = [ "lang-rust", "lang-toml", "lang-yaml", - + "lang-kotlin", ] lang-c = ["dep:tree-sitter-c"] lang-cpp = ["dep:tree-sitter-cpp"] @@ -32,6 +32,7 @@ lang-python = ["dep:tree-sitter-python"] lang-rust = ["dep:tree-sitter-rust"] lang-toml = ["dep:tree-sitter-toml-ng"] lang-yaml = ["dep:tree-sitter-yaml"] +lang-kotlin = ["dep:tree-sitter-kotlin"] [dependencies] anyhow = "1.0.86" @@ -49,6 +50,7 @@ tree-sitter-c = { version = "0.21.4", optional = true } tree-sitter-cpp = { version = "0.22.2", optional = true } tree-sitter-go = { version = "0.21.0", optional = true } tree-sitter-json = { version = "0.21.0", optional = true } +tree-sitter-kotlin = { version = "0.3.7", optional = true } tree-sitter-md = { version = "0.2.3", optional = true } tree-sitter-python = { version = "0.21.0", optional = true } tree-sitter-rust = { version = "0.21.2", optional = true } diff --git a/README.md b/README.md index eb9a925..d7d8af8 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,9 @@ typographical errors, and other mistakes that are not covered by tools like [`typos`][typos] to ensure that your source code is free from typographical heresy. -**This tool is still experimental.** - -The *goal* is to make the number of false positives low so that -it can be integrated into a CI, like [`typos`][typos]. - ## Rules -The tool only has one rule at the moment: +`typope` has only one rule at the moment: - [No space before a punctuation mark](./src/lint/punctuation.rs) @@ -24,6 +19,7 @@ The tool only has one rule at the moment: - Rust - Go +- Kotlin - Python - C++ - C diff --git a/src/lang.rs b/src/lang.rs index 49c567d..f1cc965 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -15,6 +15,8 @@ mod cpp; mod go; #[cfg(feature = "lang-json")] mod json; +#[cfg(feature = "lang-kotlin")] +mod kotlin; #[cfg(feature = "lang-markdown")] mod markdown; #[cfg(feature = "lang-python")] @@ -52,6 +54,7 @@ impl Mapping { lang!(rust, "lang-rust"); lang!(c, "lang-c"); lang!(cpp, "lang-cpp"); + lang!(kotlin, "lang-kotlin"); lang!(go, "lang-go"); lang!(python, "lang-python"); lang!(toml, "lang-toml"); diff --git a/src/lang/kotlin.rs b/src/lang/kotlin.rs new file mode 100644 index 0000000..1d6d5bb --- /dev/null +++ b/src/lang/kotlin.rs @@ -0,0 +1,80 @@ +use super::{Language, Mode}; + +impl Language { + /// Creates a language parser for Kotlin + pub fn kotlin() -> Self { + Self { + name: "kotlin", + language: tree_sitter_kotlin::language(), + extensions: &["kt"], + parser: Mode::Generic { + tree_sitter_types: &["string_content"], + }, + } + } +} + +#[cfg(test)] +mod tests { + use std::ffi::OsStr; + + use crate::lang::LintableString; + use crate::SharedSource; + + use super::Language; + + #[test] + fn exists_in_iter() { + assert!(Language::iter().any(|lang| lang.name() == "kotlin")); + } + + #[test] + fn find_from_extensions() { + for ext in Language::kotlin().extensions() { + assert_eq!( + "kotlin", + Language::from_extension(OsStr::new(ext)).unwrap().name() + ); + } + } + + #[test] + fn lintable_strings() { + let kotlin = r#" +package org.kotlinlang.play + +fun f(): String { + return "abcdef" +} + +fun main() { + var s = "foobar" + println("Hello, World! ($s) ghijkl") +} +"#; + let kotlin = SharedSource::new("file.kt", kotlin.as_bytes().to_vec()); + let mut parsed = Language::kotlin().parse(&kotlin).unwrap(); + let strings = parsed.strings(kotlin.as_ref()).collect::>(); + assert_eq!( + strings, + [ + LintableString { + offset: 60, + value: "abcdef".into() + }, + LintableString { + offset: 97, + value: "foobar".into() + }, + LintableString { + offset: 118, + value: "Hello, World! (".into() + }, + LintableString { + offset: 135, + value: ") ghijkl".into() + }, + ] + ); + } +}