diff --git a/Units/parser-elixir.r/elixir-callbacks.d/args.ctags b/Units/parser-elixir.r/elixir-callbacks.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-callbacks.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-callbacks.d/expected.tags b/Units/parser-elixir.r/elixir-callbacks.d/expected.tags new file mode 100644 index 0000000000..b82ece7998 --- /dev/null +++ b/Units/parser-elixir.r/elixir-callbacks.d/expected.tags @@ -0,0 +1,3 @@ +CallbackModule input.ex /^defmodule CallbackModule do$/;" module +new_callback input.ex /^ @callback new_callback() :: integer$/;" callback +old_callback input.ex /^ defcallback old_callback(info :: integer) :: integer$/;" callback diff --git a/Units/parser-elixir.r/elixir-callbacks.d/input.ex b/Units/parser-elixir.r/elixir-callbacks.d/input.ex new file mode 100644 index 0000000000..b554a761f7 --- /dev/null +++ b/Units/parser-elixir.r/elixir-callbacks.d/input.ex @@ -0,0 +1,8 @@ +defmodule CallbackModule do + use Behaviour + # This is the new callback syntax + @callback new_callback() :: integer + + # This is the old (deprecated) callback syntax + defcallback old_callback(info :: integer) :: integer +end diff --git a/Units/parser-elixir.r/elixir-exceptions.b/README.md b/Units/parser-elixir.r/elixir-exceptions.b/README.md new file mode 100644 index 0000000000..6d13e3b982 --- /dev/null +++ b/Units/parser-elixir.r/elixir-exceptions.b/README.md @@ -0,0 +1,5 @@ +Exceptions are defined like structs but their name is the name of module they +are defined in. For this I'll have to use a multiline regex +(`--mline-regex-`) which I don't know yet how to use. + +This is more a TODO than a bug. diff --git a/Units/parser-elixir.r/elixir-exceptions.b/expected.tags b/Units/parser-elixir.r/elixir-exceptions.b/expected.tags new file mode 100644 index 0000000000..963b628e95 --- /dev/null +++ b/Units/parser-elixir.r/elixir-exceptions.b/expected.tags @@ -0,0 +1,2 @@ +ModuleError input.ex /^defmodule ModuleError do$/;" module +ModuleError input.ex /^ defexception [:message]$/;" delegate diff --git a/Units/parser-elixir.r/elixir-exceptions.b/input.ex b/Units/parser-elixir.r/elixir-exceptions.b/input.ex new file mode 100644 index 0000000000..604cb80ab4 --- /dev/null +++ b/Units/parser-elixir.r/elixir-exceptions.b/input.ex @@ -0,0 +1,9 @@ +defmodule ErrorModule do + defexception [:message] + + @impl true + def exception(value) do + msg = "did not get what was expected, got: #{inspect(value)}" + %ErrorModule{message: msg} + end +end diff --git a/Units/parser-elixir.r/elixir-functions.d/args.ctags b/Units/parser-elixir.r/elixir-functions.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-functions.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-functions.d/expected.tags b/Units/parser-elixir.r/elixir-functions.d/expected.tags new file mode 100644 index 0000000000..0d05d65b97 --- /dev/null +++ b/Units/parser-elixir.r/elixir-functions.d/expected.tags @@ -0,0 +1,8 @@ +FunctionModule input.ex /^defmodule FunctionModule do$/;" module +one_liner_func input.ex /^ def one_liner_func, do: :baz$/;" function +func_no_params input.ex /^ def func_no_params do$/;" function +func_head input.ex /^ def func_head(string1, string2 \\\\ nil, separator \\\\ " ")$/;" function +func_one_arity input.ex /^ def func_one_arity(string1, nil, _separator) do$/;" function +normal_func input.ex /^ def normal_func(string1, string2, separator) do$/;" function +private_func input.ex /^ defp private_func(a), do: a <> " alone"$/;" function +private_func_no_params input.ex /^ defp private_func_no_params do$/;" function diff --git a/Units/parser-elixir.r/elixir-functions.d/input.ex b/Units/parser-elixir.r/elixir-functions.d/input.ex new file mode 100644 index 0000000000..90ab224409 --- /dev/null +++ b/Units/parser-elixir.r/elixir-functions.d/input.ex @@ -0,0 +1,27 @@ +defmodule FunctionModule do + def one_liner_func, do: :baz + + def func_no_params do + # + end + + # Function head + def func_head(string1, string2 \\ nil, separator \\ " ") + + # Function with 1 arity + def func_one_arity(string1, nil, _separator) do + private_function(string1) + end + + # Normal function + def normal_func(string1, string2, separator) do + string1 <> separator <> string2 + end + + # Private function + defp private_func(a), do: a <> " alone" + + defp private_func_no_params do + # + end +end diff --git a/Units/parser-elixir.r/elixir-macros.d/args.ctags b/Units/parser-elixir.r/elixir-macros.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-macros.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-macros.d/expected.tags b/Units/parser-elixir.r/elixir-macros.d/expected.tags new file mode 100644 index 0000000000..c01172751d --- /dev/null +++ b/Units/parser-elixir.r/elixir-macros.d/expected.tags @@ -0,0 +1,5 @@ +MacroModule input.ex /^defmodule MacroModule do$/;" module +macro input.ex /^ defmacro macro(expr, opts) do$/;" macro +macro_no_params input.ex /^ defmacro macro_no_params do$/;" macro +private_macro input.ex /^ defmacrop private_macro(expr, opts) do$/;" macro +private_macro_no_params input.ex /^ defmacrop private_macro_no_params do$/;" macro diff --git a/Units/parser-elixir.r/elixir-macros.d/input.ex b/Units/parser-elixir.r/elixir-macros.d/input.ex new file mode 100644 index 0000000000..2c308ad94d --- /dev/null +++ b/Units/parser-elixir.r/elixir-macros.d/input.ex @@ -0,0 +1,17 @@ +defmodule MacroModule do + defmacro macro(expr, opts) do + # + end + + defmacro macro_no_params do + # + end + + defmacrop private_macro(expr, opts) do + # + end + + defmacrop private_macro_no_params do + # + end +end diff --git a/Units/parser-elixir.r/elixir-modules.d/args.ctags b/Units/parser-elixir.r/elixir-modules.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-modules.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-modules.d/expected.tags b/Units/parser-elixir.r/elixir-modules.d/expected.tags new file mode 100644 index 0000000000..cd7f43fcd0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-modules.d/expected.tags @@ -0,0 +1,3 @@ +Foo input.ex /^defmodule Foo do$/;" module +Bar input.ex /^defmodule Foo.Bar do$/;" module +Baz input.ex /^ defmodule Baz do$/;" module diff --git a/Units/parser-elixir.r/elixir-modules.d/input.ex b/Units/parser-elixir.r/elixir-modules.d/input.ex new file mode 100644 index 0000000000..5fb1a9a137 --- /dev/null +++ b/Units/parser-elixir.r/elixir-modules.d/input.ex @@ -0,0 +1,7 @@ +defmodule Foo do +end + +defmodule Foo.Bar do + defmodule Baz do + end +end diff --git a/Units/parser-elixir.r/elixir-records.d/args.ctags b/Units/parser-elixir.r/elixir-records.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-records.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-records.d/expected.tags b/Units/parser-elixir.r/elixir-records.d/expected.tags new file mode 100644 index 0000000000..170553a640 --- /dev/null +++ b/Units/parser-elixir.r/elixir-records.d/expected.tags @@ -0,0 +1,3 @@ +RecordsModule input.ex /^defmodule RecordsModule do$/;" module +user1 input.ex /^ Record.defrecord(:user1, name: "megan", age: "25")$/;" record +user2 input.ex /^ Record.defrecordp :user2, name: "ivan", age: "23"$/;" record diff --git a/Units/parser-elixir.r/elixir-records.d/input.ex b/Units/parser-elixir.r/elixir-records.d/input.ex new file mode 100644 index 0000000000..c5c146fe0a --- /dev/null +++ b/Units/parser-elixir.r/elixir-records.d/input.ex @@ -0,0 +1,7 @@ +defmodule RecordsModule do + require Record + Record.defrecord(:user1, name: "megan", age: "25") + Record.defrecordp :user2, name: "ivan", age: "23" + # This is not a typo but an intentional bad test, used to test the parser + Record.defrecordp:bad, name: "ivan", age: "23" +end diff --git a/Units/parser-elixir.r/elixir-sign-operators.d/args.ctags b/Units/parser-elixir.r/elixir-sign-operators.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-sign-operators.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-sign-operators.d/expected.tags b/Units/parser-elixir.r/elixir-sign-operators.d/expected.tags new file mode 100644 index 0000000000..20f6ea940b --- /dev/null +++ b/Units/parser-elixir.r/elixir-sign-operators.d/expected.tags @@ -0,0 +1,20 @@ +OperatorModule input.ex /^defmodule OperatorModule do$/;" module ++ input.ex /^ def a + b, do: max(a, b)$/;" operator +- input.ex /^ def a - b, do: max(a, b)$/;" operator +* input.ex /^ def a * b, do: max(a, b)$/;" operator +/ input.ex /^ def a \/ b, do: max(a, b)$/;" operator += input.ex /^ def a = b, do: max(a, b)$/;" operator +. input.ex /^ def a . b, do: max(a, b)$/;" operator +| input.ex /^ def a | b, do: max(a, b)$/;" operator +||| input.ex /^ def _ ||| b, do: max(a, b)$/;" operator +&&& input.ex /^ def a &&& _, do: max(a, b)$/;" operator +<<< input.ex /^ def a <<< b, do: max(a, b)$/;" operator +>>> input.ex /^ defp a >>> b, do: max(a, b)$/;" operator +<<~ input.ex /^ defp _ <<~ _, do: max(a, b)$/;" operator +~>> input.ex /^ defp a ~>> b, do: max(a, b)$/;" operator +<~ input.ex /^ defmacro a <~ b, do: max(a, b)$/;" operator +~> input.ex /^ defmacro _ ~> b, do: max(a, b)$/;" operator +<~> input.ex /^ defmacro a <~> _, do: max(a, b)$/;" operator +<|> input.ex /^ defmacrop a <|> b, do: max(a, b)$/;" operator +^^^ input.ex /^ defmacrop _ ^^^ _, do: max(a, b)$/;" operator +~~~ input.ex /^ defmacrop a ~~~ b, do: max(a, b)$/;" operator diff --git a/Units/parser-elixir.r/elixir-sign-operators.d/input.ex b/Units/parser-elixir.r/elixir-sign-operators.d/input.ex new file mode 100644 index 0000000000..18655ca314 --- /dev/null +++ b/Units/parser-elixir.r/elixir-sign-operators.d/input.ex @@ -0,0 +1,24 @@ +defmodule OperatorModule do + def a + b, do: max(a, b) + def a - b, do: max(a, b) + def a * b, do: max(a, b) + def a / b, do: max(a, b) + def a = b, do: max(a, b) + def a . b, do: max(a, b) + + # The 13 operators bellow are ALL the operators that Elixir is CAPABLE of + # parsing and are not used by default, so the user can + def a | b, do: max(a, b) + def _ ||| b, do: max(a, b) + def a &&& _, do: max(a, b) + def a <<< b, do: max(a, b) + defp a >>> b, do: max(a, b) + defp _ <<~ _, do: max(a, b) + defp a ~>> b, do: max(a, b) + defmacro a <~ b, do: max(a, b) + defmacro _ ~> b, do: max(a, b) + defmacro a <~> _, do: max(a, b) + defmacrop a <|> b, do: max(a, b) + defmacrop _ ^^^ _, do: max(a, b) + defmacrop a ~~~ b, do: max(a, b) +end diff --git a/Units/parser-elixir.r/elixir-simple.d/args.ctags b/Units/parser-elixir.r/elixir-simple.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-simple.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-simple.d/expected.tags b/Units/parser-elixir.r/elixir-simple.d/expected.tags new file mode 100644 index 0000000000..3e64129479 --- /dev/null +++ b/Units/parser-elixir.r/elixir-simple.d/expected.tags @@ -0,0 +1,10 @@ +MyList input.ex /^defmodule MyList do$/;" module +reverse input.ex /^ defdelegate reverse(list), to: Enum$/;" delegate +other_reverse input.ex /^ defdelegate other_reverse(list), to: Enum, as: :reverse$/;" delegate +Size input.ex /^defprotocol Size do$/;" protocol +size input.ex /^ def size(data)$/;" function +MyGuards input.ex /^defmodule Integer.MyGuards do$/;" module +is_even input.ex /^ defguard is_even(value) when is_integer(value) and rem(value, 2) == 0$/;" guard +is_odd input.ex /^ defguardp is_odd(value) when is_integer(value) and rem(value, 2) != 0$/;" guard +Size input.ex /^defimpl Size, for: BitString do$/;" implementation +size input.ex /^ def size(binary), do: byte_size(binary)$/;" function diff --git a/Units/parser-elixir.r/elixir-simple.d/input.ex b/Units/parser-elixir.r/elixir-simple.d/input.ex new file mode 100644 index 0000000000..a35d652d41 --- /dev/null +++ b/Units/parser-elixir.r/elixir-simple.d/input.ex @@ -0,0 +1,37 @@ +# Most of this code is taken from the official Elixir documentation. +# With comments and modifications +# by Ivan Gonzalez Polanco +# +# This code doesn't compile, since it's supposed to test de ctags elixir +# parser, not the elixir elixir parser. + +# +# d delegates (defdelegate ...) +# +defmodule MyList do + defdelegate reverse(list), to: Enum + defdelegate other_reverse(list), to: Enum, as: :reverse +end + +# +# p protocols (defprotocol ...) +# +defprotocol Size do + @doc "Calculates the size (and not the length!) of a data structure" + def size(data) +end + +# +# g guards (defguard ...) +# +defmodule Integer.MyGuards do + defguard is_even(value) when is_integer(value) and rem(value, 2) == 0 + defguardp is_odd(value) when is_integer(value) and rem(value, 2) != 0 +end + +# +# i implementations (defimpl ...) +# +defimpl Size, for: BitString do + def size(binary), do: byte_size(binary) +end diff --git a/Units/parser-elixir.r/elixir-tests.d/args.ctags b/Units/parser-elixir.r/elixir-tests.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-tests.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-tests.d/expected.tags b/Units/parser-elixir.r/elixir-tests.d/expected.tags new file mode 100644 index 0000000000..38d4814740 --- /dev/null +++ b/Units/parser-elixir.r/elixir-tests.d/expected.tags @@ -0,0 +1,3 @@ +TestModule input.ex /^defmodule TestModule do$/;" module +good with spaces input.ex /^ test "good with spaces" do$/;" test +good with parens input.ex /^ test("good with parens") do$/;" test diff --git a/Units/parser-elixir.r/elixir-tests.d/input.ex b/Units/parser-elixir.r/elixir-tests.d/input.ex new file mode 100644 index 0000000000..75929f5e0f --- /dev/null +++ b/Units/parser-elixir.r/elixir-tests.d/input.ex @@ -0,0 +1,22 @@ +defmodule TestModule do + use ExUnit.Case, async: true + + test "good with spaces" do + assert 1 + 1 == 2 + end + + test("good with parens") do + assert 1 + 1 == 2 + end + test"bad without spaces" do + assert 1 + 1 == 2 + end + + test "bad without 'do' word" + assert 1 + 1 == 2 + end + + test 'bad with single quotes' do + assert 1 + 1 == 2 + end +end diff --git a/Units/parser-elixir.r/elixir-word-operators.d/args.ctags b/Units/parser-elixir.r/elixir-word-operators.d/args.ctags new file mode 100644 index 0000000000..39d2c946a0 --- /dev/null +++ b/Units/parser-elixir.r/elixir-word-operators.d/args.ctags @@ -0,0 +1,2 @@ +--sort=no +--fields=+K diff --git a/Units/parser-elixir.r/elixir-word-operators.d/expected.tags b/Units/parser-elixir.r/elixir-word-operators.d/expected.tags new file mode 100644 index 0000000000..b41592a4e1 --- /dev/null +++ b/Units/parser-elixir.r/elixir-word-operators.d/expected.tags @@ -0,0 +1,7 @@ +OperatorModule input.ex /^defmodule OperatorModule do$/;" module +and input.ex /^ def a and b, do: max(a, b)$/;" operator +or input.ex /^ def a or b, do: max(a, b)$/;" operator +not input.ex /^ defp a not b, do: max(a, b)$/;" operator +in input.ex /^ defmacro a in b, do: max(a, b)$/;" operator +not in input.ex /^ defmacrop a not in b, do: max(a, b)$/;" operator +when input.ex /^ defmacrop a when b, do: max(a, b)$/;" operator diff --git a/Units/parser-elixir.r/elixir-word-operators.d/input.ex b/Units/parser-elixir.r/elixir-word-operators.d/input.ex new file mode 100644 index 0000000000..c52945b96e --- /dev/null +++ b/Units/parser-elixir.r/elixir-word-operators.d/input.ex @@ -0,0 +1,8 @@ +defmodule OperatorModule do + def a and b, do: max(a, b) + def a or b, do: max(a, b) + defp a not b, do: max(a, b) + defmacro a in b, do: max(a, b) + defmacrop a not in b, do: max(a, b) + defmacrop a when b, do: max(a, b) +end diff --git a/docs/news.rst b/docs/news.rst index 0cb951eeb3..480c9964a9 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -52,6 +52,7 @@ The following parsers have been added: * Diff * DTD * DTS +* Elixir *optlib* * Elm *optlib* * Falcon * Gdbinit script *optlib* diff --git a/main/parsers_p.h b/main/parsers_p.h index 289875ab59..7e86b25c2c 100644 --- a/main/parsers_p.h +++ b/main/parsers_p.h @@ -70,6 +70,7 @@ DTSParser, \ DosBatchParser, \ EiffelParser, \ + ElixirParser, \ ElmParser, \ ErlangParser, \ FalconParser, \ diff --git a/makefiles/optlib2c_input.mak b/makefiles/optlib2c_input.mak index 11b01e827d..84c7507f57 100644 --- a/makefiles/optlib2c_input.mak +++ b/makefiles/optlib2c_input.mak @@ -3,7 +3,8 @@ OPTLIB2C_INPUT = \ optlib/RSpec.ctags \ optlib/cmake.ctags \ optlib/ctags-optlib.ctags \ - optlib/elm.ctags \ + optlib/elixir.ctags \ + optlib/elm.ctags \ optlib/gdbinit.ctags \ optlib/man.ctags \ optlib/markdown.ctags \ diff --git a/optlib/elixir.c b/optlib/elixir.c new file mode 100644 index 0000000000..e1838b0549 --- /dev/null +++ b/optlib/elixir.c @@ -0,0 +1,111 @@ +/* + * Generated by ./misc/optlib2c from optlib/elixir.ctags, Don't edit this manually. + */ +#include "general.h" +#include "parse.h" +#include "routines.h" +#include "field.h" +#include "xtag.h" + + +static void initializeElixirParser (const langType language CTAGS_ATTR_UNUSED) +{ +} + +extern parserDefinition* ElixirParser (void) +{ + static const char *const extensions [] = { + "ex", + "exs", + NULL + }; + + static const char *const aliases [] = { + NULL + }; + + static const char *const patterns [] = { + NULL + }; + + static kindDefinition ElixirKindTable [] = { + { + true, 'f', "function", "functions (def ...)", + }, + { + true, 'c', "callback", "callbacks (defcallback ...)", + }, + { + true, 'd', "delegate", "delegates (defdelegate ...)", + }, + { + true, 'e', "exception", "exceptions (defexception ...)", + }, + { + true, 'g', "guard", "guards (defguard ...)", + }, + { + true, 'i', "implementation", "implementations (defimpl ...)", + }, + { + true, 'a', "macro", "macros (defmacro ...)", + }, + { + true, 'o', "operator", "operators (e.g. \"defmacro a <<< b\")", + }, + { + true, 'm', "module", "modules (defmodule ...)", + }, + { + true, 'p', "protocol", "protocols (defprotocol...)", + }, + { + true, 'r', "record", "records (defrecord...)", + }, + { + true, 't', "test", "tests (test ...)", + }, + }; + static tagRegexTable ElixirTagRegexTable [] = { + {"^[ \t]*def((p?)|macro(p?))[ \t]+([a-zA-Z0-9_?!]+)[ \t]+([\\|\\^/&<>~.=!*+-]{1,3}|and|or|in|not|when|not in)[ \t]+[a-zA-Z0-9_?!]", "\\5", + "o", "{exclusive}", NULL, false}, + {"^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)(.[^\\|\\^/&<>~.=!*+-]+)", "\\2", + "f", NULL, NULL, false}, + {"^[ \t]*(@|def)callback[ \t]+([a-z_][a-zA-Z0-9_?!]*)", "\\2", + "c", NULL, NULL, false}, + {"^[ \t]*defdelegate[ \t]+([a-z_][a-zA-Z0-9_?!]*)", "\\1", + "d", NULL, NULL, false}, + {"^[ \t]*defexception[ \t]+([A-Z][a-zA-Z0-9_]*\\.)*([A-Z][a-zA-Z0-9_?!]*)", "\\2", + "e", NULL, NULL, false}, + {"^[ \t]*defguard(p?)[ \t]+(is_[a-zA-Z0-9_?!]+)", "\\2", + "g", NULL, NULL, false}, + {"^[ \t]*defimpl[ \t]+([A-Z][a-zA-Z0-9_]*\\.)*([A-Z][a-zA-Z0-9_?!]*)", "\\2", + "i", NULL, NULL, false}, + {"^[ \t]*defmacro(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)(.[^\\|\\^/&<>~.=!*+-]+)", "\\2", + "a", NULL, NULL, false}, + {"^[ \t]*defmodule[ \t]+([A-Z][a-zA-Z0-9_]*\\.)*([A-Z][a-zA-Z0-9_?!]*)", "\\2", + "m", NULL, NULL, false}, + {"^[ \t]*defprotocol[ \t]+([A-Z][a-zA-Z0-9_]*\\.)*([A-Z][a-zA-Z0-9_?!]*)", "\\2", + "p", NULL, NULL, false}, + {"^[ \t]*Record\\.defrecord(p?)[ \t(]+:([a-zA-Z0-9_]+)(\\)?)", "\\2", + "r", NULL, NULL, false}, + {"^[ \t]*test[ \t(]+\"([a-z_][a-zA-Z0-9_?! ]*)\"*(\\)?)[ \t]*do", "\\1", + "t", NULL, NULL, false}, + }; + + + parserDefinition* const def = parserNew ("Elixir"); + + def->enabled = true; + def->extensions = extensions; + def->patterns = patterns; + def->aliases = aliases; + def->method = METHOD_NOT_CRAFTED|METHOD_REGEX; + def->kindTable = ElixirKindTable; + def->kindCount = ARRAY_SIZE(ElixirKindTable); + def->tagRegexTable = ElixirTagRegexTable; + def->tagRegexCount = ARRAY_SIZE(ElixirTagRegexTable); + def->initialize = initializeElixirParser; + + return def; +} diff --git a/optlib/elixir.ctags b/optlib/elixir.ctags new file mode 100644 index 0000000000..6a57a817cf --- /dev/null +++ b/optlib/elixir.ctags @@ -0,0 +1,79 @@ +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to +# + +# +# WHEN FIXING A BUG OF THIS PARSER, WORK WITH THE UPSTREAM PROJECT. +# + +# +# This file is imported from https://github.com/mmorearty/elixir-ctags +# by Masatake YAMATO with some modifications. +# See https://github.com/mmorearty/elixir-ctags/issues/5 and +# https://github.com/universal-ctags/ctags/issues/1758#issuecomment-391692762. +# @dylan-chong and @FredrikAugust realized this u-ctags integration. +# + +# +# * Put the original LICENSE file as the header of the .ctags. +# * Use --map= option instead of --langmap because optlib2c doesn't handle +# --langmap option. +# * Define kinds explicitly with --kinddef- option. +# * Remove backslashes before double quotes chars in the regex pattern for +# "test". +# * Use singular forms for kind names. +# + +--langdef=Elixir + +--map-Elixir=+.ex +--map-Elixir=+.exs + +--kinddef-Elixir=f,function,functions (def ...) +--kinddef-Elixir=c,callback,callbacks (defcallback ...) +--kinddef-Elixir=d,delegate,delegates (defdelegate ...) +--kinddef-Elixir=e,exception,exceptions (defexception ...) +--kinddef-Elixir=g,guard,guards (defguard ...) +--kinddef-Elixir=i,implementation,implementations (defimpl ...) +--kinddef-Elixir=a,macro,macros (defmacro ...) +--kinddef-Elixir=o,operator,operators (e.g. "defmacro a <<< b") +--kinddef-Elixir=m,module,modules (defmodule ...) +--kinddef-Elixir=p,protocol,protocols (defprotocol...) +--kinddef-Elixir=r,record,records (defrecord...) +--kinddef-Elixir=t,test,tests (test ...) + +--regex-Elixir=/^[ \t]*def((p?)|macro(p?))[ \t]+([a-zA-Z0-9_?!]+)[ \t]+([\|\^\/&<>~.=!*+-]{1,3}|and|or|in|not|when|not in)[ \t]+[a-zA-Z0-9_?!]/\5/o/{exclusive} +--regex-Elixir=/^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)(.[^\|\^\/&<>~.=!*+-]+)/\2/f/ +--regex-Elixir=/^[ \t]*(@|def)callback[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\2/c/ +--regex-Elixir=/^[ \t]*defdelegate[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/d/ +--regex-Elixir=/^[ \t]*defexception[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/e/ +--regex-Elixir=/^[ \t]*defguard(p?)[ \t]+(is_[a-zA-Z0-9_?!]+)/\2/g/ +--regex-Elixir=/^[ \t]*defimpl[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/i/ +--regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)(.[^\|\^\/&<>~.=!*+-]+)/\2/a/ +--regex-Elixir=/^[ \t]*defmodule[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/m/ +--regex-Elixir=/^[ \t]*defprotocol[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/p/ +--regex-Elixir=/^[ \t]*Record\.defrecord(p?)[ \t(]+:([a-zA-Z0-9_]+)(\)?)/\2/r/ +--regex-Elixir=/^[ \t]*test[ \t(]+"([a-z_][a-zA-Z0-9_?! ]*)"*(\)?)[ \t]*do/\1/t/ diff --git a/win32/ctags_vs2013.vcxproj b/win32/ctags_vs2013.vcxproj index bb9f9d9cd6..9884852206 100644 --- a/win32/ctags_vs2013.vcxproj +++ b/win32/ctags_vs2013.vcxproj @@ -142,6 +142,7 @@ + diff --git a/win32/ctags_vs2013.vcxproj.filters b/win32/ctags_vs2013.vcxproj.filters index 19eb148175..fda10a27e6 100644 --- a/win32/ctags_vs2013.vcxproj.filters +++ b/win32/ctags_vs2013.vcxproj.filters @@ -180,6 +180,9 @@ Source Files\optlib + + Source Files\optlib + Source Files\optlib