diff --git a/CHANGELOG.md b/CHANGELOG.md index d62702fc4..b2e18508b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### Parsing -Updated to the latest tree-sitter parser for F#, Pascal and Swift. +Updated to the latest tree-sitter parser for Erlang, F#, Pascal and +Swift. ## 0.63 (released 11th February 2025) diff --git a/Cargo.lock b/Cargo.lock index 4e52149a1..af5c900b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,6 +280,7 @@ dependencies = [ "tree-sitter-cpp", "tree-sitter-css", "tree-sitter-elixir", + "tree-sitter-erlang", "tree-sitter-fsharp", "tree-sitter-go", "tree-sitter-haskell", @@ -1064,6 +1065,16 @@ dependencies = [ "tree-sitter-language", ] +[[package]] +name = "tree-sitter-erlang" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12548f9d4a253cd4095c2dd975d18cb6d6f599f902022233c8af0c57196d0042" +dependencies = [ + "cc", + "tree-sitter-language", +] + [[package]] name = "tree-sitter-fsharp" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 6d6dbc71b..c34b7a874 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,6 +104,7 @@ tree-sitter-nix = "0.0.2" tree-sitter-pascal = "0.10.0" tree-sitter-swift = "0.7.0" tree-sitter-fsharp = "0.1.0" +tree-sitter-erlang = "0.12.0" [dev-dependencies] # assert_cmd 2.0.10 requires predicates 3. diff --git a/build.rs b/build.rs index 52670ec72..f6fb75820 100644 --- a/build.rs +++ b/build.rs @@ -112,11 +112,6 @@ fn main() { src_dir: "vendored_parsers/tree-sitter-elvish-src", extra_files: vec![], }, - TreeSitterParser { - name: "tree-sitter-erlang", - src_dir: "vendored_parsers/tree-sitter-erlang-src", - extra_files: vec![], - }, TreeSitterParser { name: "tree-sitter-gleam", src_dir: "vendored_parsers/tree-sitter-gleam-src", diff --git a/sample_files/compare.expected b/sample_files/compare.expected index 80c2307ee..302b7355e 100644 --- a/sample_files/compare.expected +++ b/sample_files/compare.expected @@ -74,7 +74,7 @@ sample_files/elvish_1.elv sample_files/elvish_2.elv 93af1d46752d57db84011ca7482ae842 - sample_files/erlang_1.erl sample_files/erlang_2.erl -dccdb8f65d2f099ab1a8cb66011376a2 - +4c3e2bd1f0918ed339e87a5f8e0b05cb - sample_files/f_sharp_1.fs sample_files/f_sharp_2.fs 25253b18ef64469c67cf9a7131c8c125 - diff --git a/src/parse/guess_language.rs b/src/parse/guess_language.rs index 1a88cbf6c..fe7bff4bf 100644 --- a/src/parse/guess_language.rs +++ b/src/parse/guess_language.rs @@ -265,6 +265,9 @@ pub(crate) fn language_globs(language: Language) -> Vec { "*.xrl", "*.yrl", "Emakefile", + "rebar.config", + "rebar.config.lock", + "rebar.lock", ], FSharp => &["*.fs", "*.fsx", "*.fsi"], Gleam => &["*.gleam"], diff --git a/src/parse/tree_sitter_parser.rs b/src/parse/tree_sitter_parser.rs index eb4436acc..90f783a31 100644 --- a/src/parse/tree_sitter_parser.rs +++ b/src/parse/tree_sitter_parser.rs @@ -69,7 +69,6 @@ extern "C" { fn tree_sitter_elisp() -> ts::Language; fn tree_sitter_elm() -> ts::Language; fn tree_sitter_elvish() -> ts::Language; - fn tree_sitter_erlang() -> ts::Language; fn tree_sitter_gleam() -> ts::Language; fn tree_sitter_hare() -> ts::Language; fn tree_sitter_hack() -> ts::Language; @@ -359,7 +358,9 @@ pub(crate) fn from_language(language: guess::Language) -> TreeSitterConfig { } } Erlang => { - let language = unsafe { tree_sitter_erlang() }; + let language_fn = tree_sitter_erlang::LANGUAGE; + let language = tree_sitter::Language::new(language_fn); + TreeSitterConfig { language: language.clone(), atom_nodes: [].into_iter().collect(), diff --git a/vendored_parsers/highlights/erlang.scm b/vendored_parsers/highlights/erlang.scm index e33597f62..8170a72a1 100644 --- a/vendored_parsers/highlights/erlang.scm +++ b/vendored_parsers/highlights/erlang.scm @@ -1,19 +1,232 @@ -"after" @keyword -"case" @keyword -"catch" @keyword -"end" @keyword -"fun" @keyword -"if" @keyword -"of" @keyword -"receive" @keyword -"try" @keyword -"when" @keyword - -"=" @operator -":=" @operator -"::" @operator -"->" @operator -"<-" @operator +;; https://github.com/WhatsApp/tree-sitter-erlang/blob/370cea629eb62a8686504b9fb3252a5e1ae55313/queries/highlights.scm +;; Copyright (c) Facebook, Inc. and its affiliates. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +;; --------------------------------------------------------------------- + +;; Based initially on the contents of https://github.com/WhatsApp/tree-sitter-erlang/issues/2 by @Wilfred +;; and https://github.com/the-mikedavis/tree-sitter-erlang/blob/main/queries/highlights.scm +;; +;; The tests are also based on those in +;; https://github.com/the-mikedavis/tree-sitter-erlang/tree/main/test/highlight +;; + +;; Last match wins in this file. +;; As of https://github.com/tree-sitter/tree-sitter/blob/master/CHANGELOG.md#breaking-1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Primitive types (string) @string -(char) @string +(char) @constant +(integer) @number +(var) @variable +(atom) @string.special.symbol + +;;; Comments +((var) @comment.discard + (#match? @comment.discard "^_")) + +(dotdotdot) @comment.discard +(comment) @comment + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Functions +(fa fun: (atom) @function) +(type_name name: (atom) @function) +(call expr: (atom) @function) +(function_clause name: (atom) @function) +(internal_fun fun: (atom) @function) + +;; This is a fudge, we should check that the operator is '/' +;; But our grammar does not (currently) provide it +(binary_op_expr lhs: (atom) @function rhs: (integer)) + +;; Others +(remote_module module: (atom) @module) +(remote fun: (atom) @function) +(macro_call_expr name: (var) @constant) +(macro_call_expr name: (var) @keyword.directive args: (_) ) +(macro_call_expr name: (atom) @keyword.directive) +(record_field_name name: (atom) @property) +(record_name name: (atom) @type) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Attributes + +;; module attribute +(module_attribute + name: (atom) @module) + +;; behaviour +(behaviour_attribute name: (atom) @module) + +;; export + +;; Import attribute +(import_attribute + module: (atom) @module) + +;; export_type + +;; optional_callbacks + +;; compile +(compile_options_attribute + options: (tuple + expr: (atom) + expr: (list + exprs: (binary_op_expr + lhs: (atom) + rhs: (integer))))) + +;; file attribute + +;; record +(record_decl name: (atom) @type) +(record_decl name: (macro_call_expr name: (var) @constant)) +(record_field name: (atom) @property) + +;; type alias + +;; opaque + +;; Spec attribute +(spec fun: (atom) @function) +(spec + module: (module name: (atom) @module) + fun: (atom) @function) + +;; callback +(callback fun: (atom) @function) + +;; wild attribute +(wild_attribute name: (attr_name name: (atom) @keyword)) + +;; fun decl + +;; include/include_lib + +;; ifdef/ifndef +(pp_ifdef name: (_) @keyword.directive) +(pp_ifndef name: (_) @keyword.directive) + +;; define +(pp_define + lhs: (macro_lhs + name: (var) @constant)) +(pp_define + lhs: (macro_lhs + name: (_) @keyword.directive + args: (var_args args: (var)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Reserved words +[ "after" + "and" + "band" + "begin" + "behavior" + "behaviour" + "bnot" + "bor" + "bsl" + "bsr" + "bxor" + "callback" + "case" + "catch" + "compile" + "define" + "div" + "elif" + "else" + "end" + "endif" + "export" + "export_type" + "file" + "fun" + "if" + "ifdef" + "ifndef" + "import" + "include" + "include_lib" + "module" + "of" + "opaque" + "optional_callbacks" + "or" + "receive" + "record" + "spec" + "try" + "type" + "undef" + "unit" + "when" + "xor"] @keyword + +["andalso" "orelse"] @keyword.operator + +;; Punctuation +["," "." ";"] @punctuation.delimiter +["(" ")" "{" "}" "[" "]" "<<" ">>"] @punctuation.bracket + +;; Operators +["!" + "->" + "<-" + "#" + "::" + "|" + ":" + "=" + "||" + + "+" + "-" + "bnot" + "not" + + "/" + "*" + "div" + "rem" + "band" + "and" + + "+" + "-" + "bor" + "bxor" + "bsl" + "bsr" + "or" + "xor" + + "++" + "--" + + "==" + "/=" + "=<" + "<" + ">=" + ">" + "=:=" + "=/=" + ] @operator +