diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 06e57647..b424f105 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: strategy: matrix: otp: [26.0.2] - elixir: [1.15.4] + elixir: [1.15.4, 1.16.0-rc.0] steps: - uses: actions/checkout@v2 diff --git a/lib/next_ls.ex b/lib/next_ls.ex index 2d901b8a..1cc53314 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -946,6 +946,7 @@ defmodule NextLS do FROM "symbols" sym WHERE sym.file = ? AND sym.line = ? + AND (sym.type in ('defstruct', 'defmodule') OR ? BETWEEN sym.start_column AND sym.end_column) ORDER BY sym.id ASC LIMIT 1 """ @@ -960,7 +961,7 @@ defmodule NextLS do LIMIT 1 """ - case DB.query(database, definition_query, [file, line]) do + case DB.query(database, definition_query, [file, line, col]) do [[module, "defmodule", _]] -> {:module, module} diff --git a/lib/next_ls/db.ex b/lib/next_ls/db.ex index 90ab1132..53a1b6a9 100644 --- a/lib/next_ls/db.ex +++ b/lib/next_ls/db.ex @@ -90,36 +90,46 @@ defmodule NextLS.DB do [mod] ) + {start_column, end_column} = + infer_columns_from_references(conn, s.logger, file, module_line, "defmodule") + __query__( {conn, s.logger}, ~Q""" - INSERT INTO symbols (module, file, type, name, line, 'column', source) - VALUES (?, ?, ?, ?, ?, ?, ?); + INSERT INTO symbols (module, file, type, name, line, start_column, end_column, source) + VALUES (?, ?, ?, ?, ?, ?, ?, ?); """, - [mod, file, "defmodule", mod, module_line, 1, source] + [mod, file, "defmodule", mod, module_line, start_column, end_column, source] ) if struct do {_, _, meta, _} = defs[:__struct__] + {start_column, end_column} = + infer_columns_from_references(conn, s.logger, file, meta[:line], "defstruct") + __query__( {conn, s.logger}, ~Q""" - INSERT INTO symbols (module, file, type, name, line, 'column', source) - VALUES (?, ?, ?, ?, ?, ?, ?); + INSERT INTO symbols (module, file, type, name, line, start_column, end_column, source) + VALUES (?, ?, ?, ?, ?, ?, ?, ?); """, - [mod, file, "defstruct", "%#{Macro.to_string(mod)}{}", meta[:line], 1, source] + [mod, file, "defstruct", "%#{Macro.to_string(mod)}{}", meta[:line], start_column, end_column, source] ) end for {name, {:v1, type, _meta, clauses}} <- defs, {meta, _, _, _} <- clauses do + # Elixir versions older than 1.16 did not provide column metadata + column_start = meta[:column] || 1 + name = to_string(name) + __query__( {conn, s.logger}, ~Q""" - INSERT INTO symbols (module, file, type, name, line, 'column', source) - VALUES (?, ?, ?, ?, ?, ?, ?); + INSERT INTO symbols (module, file, type, name, line, start_column, end_column, source) + VALUES (?, ?, ?, ?, ?, ?, ?, ?); """, - [mod, file, type, name, meta[:line], meta[:column] || 1, source] + [mod, file, type, name, meta[:line], column_start, column_start + String.length(name), source] ) end @@ -127,10 +137,10 @@ defmodule NextLS.DB do __query__( {conn, s.logger}, ~Q""" - INSERT INTO symbols (module, file, type, name, line, 'column', source) - VALUES (?, ?, ?, ?, ?, ?, ?); + INSERT INTO symbols (module, file, type, name, line, start_column, end_column, source) + VALUES (?, ?, ?, ?, ?, ?, ?, ?); """, - [mod, file, type, name, line, column, source] + [mod, file, type, name, line, column, column + String.length(name), source] ) end @@ -218,4 +228,22 @@ defmodule NextLS.DB do arg end end + + defp infer_columns_from_references(conn, logger, file, line, identifier) do + result = + __query__( + {conn, logger}, + ~Q""" + SELECT start_column, end_column + FROM "references" + WHERE file = ? AND start_line = ? AND end_line = ? AND identifier = ? + """, + [file, line, line, identifier] + ) + + case result do + [[start_column, end_column]] -> {start_column, end_column} + _unknown -> {1, 1} + end + end end diff --git a/lib/next_ls/db/schema.ex b/lib/next_ls/db/schema.ex index 209e04a6..d0898a1c 100644 --- a/lib/next_ls/db/schema.ex +++ b/lib/next_ls/db/schema.ex @@ -23,7 +23,7 @@ defmodule NextLS.DB.Schema do alias NextLS.DB - @version 5 + @version 6 def init(conn) do # FIXME: this is odd tech debt. not a big deal but is confusing @@ -81,7 +81,8 @@ defmodule NextLS.DB.Schema do type text NOT NULL, name text NOT NULL, line integer NOT NULL, - column integer NOT NULL, + start_column integer NOT NULL, + end_column integer NOT NULL, source text NOT NULL DEFAULT 'user', inserted_at text NOT NULL DEFAULT CURRENT_TIMESTAMP );