From 04fbb1de4488852c3ba332898b17180500f8984e Mon Sep 17 00:00:00 2001 From: Jonathon <32371757+jwhite510@users.noreply.github.com> Date: Fri, 4 Nov 2022 05:07:22 -0400 Subject: Enable new diff option linematch (#14537) Co-authored-by: Lewis Russell --- src/nvim/lua/xdiff.c | 122 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 26 deletions(-) (limited to 'src/nvim/lua/xdiff.c') diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index b2b5dfedee..428a33cdad 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -10,12 +10,16 @@ #include #include "nvim/api/private/helpers.h" +#include "nvim/linematch.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" #include "nvim/lua/xdiff.h" #include "nvim/vim.h" #include "xdiff/xdiff.h" +#define COMPARED_BUFFER0 (1 << 0) +#define COMPARED_BUFFER1 (1 << 1) + typedef enum { kNluaXdiffModeUnified = 0, kNluaXdiffModeOnHunkCB, @@ -25,12 +29,72 @@ typedef enum { typedef struct { lua_State *lstate; Error *err; + mmfile_t *ma; + mmfile_t *mb; + bool linematch; + bool iwhite; } hunkpriv_t; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "lua/xdiff.c.generated.h" #endif +static void lua_pushhunk(lua_State *lstate, long start_a, long count_a, long start_b, long count_b) +{ + lua_createtable(lstate, 0, 0); + lua_pushinteger(lstate, start_a); + lua_rawseti(lstate, -2, 1); + lua_pushinteger(lstate, count_a); + lua_rawseti(lstate, -2, 2); + lua_pushinteger(lstate, start_b); + lua_rawseti(lstate, -2, 3); + lua_pushinteger(lstate, count_b); + lua_rawseti(lstate, -2, 4); + lua_rawseti(lstate, -2, (signed)lua_objlen(lstate, -2) + 1); +} + +static void get_linematch_results(lua_State *lstate, mmfile_t *ma, mmfile_t *mb, long start_a, + long count_a, long start_b, long count_b, bool iwhite) +{ + // get the pointer to char of the start of the diff to pass it to linematch algorithm + const char *diff_begin[2] = { ma->ptr, mb->ptr }; + int diff_length[2] = { (int)count_a, (int)count_b }; + + fastforward_buf_to_lnum(&diff_begin[0], (size_t)start_a); + fastforward_buf_to_lnum(&diff_begin[1], (size_t)start_b); + + int *decisions = NULL; + size_t decisions_length = linematch_nbuffers(diff_begin, diff_length, 2, &decisions, iwhite); + + long lnuma = start_a, lnumb = start_b; + + long hunkstarta = lnuma; + long hunkstartb = lnumb; + long hunkcounta = 0; + long hunkcountb = 0; + for (size_t i = 0; i < decisions_length; i++) { + if (i && (decisions[i - 1] != decisions[i])) { + lua_pushhunk(lstate, hunkstarta, hunkcounta, hunkstartb, hunkcountb); + + hunkstarta = lnuma; + hunkstartb = lnumb; + hunkcounta = 0; + hunkcountb = 0; + // create a new hunk + } + if (decisions[i] & COMPARED_BUFFER0) { + lnuma++; + hunkcounta++; + } + if (decisions[i] & COMPARED_BUFFER1) { + lnumb++; + hunkcountb++; + } + } + lua_pushhunk(lstate, hunkstarta, hunkcounta, hunkstartb, hunkcountb); + xfree(decisions); +} + static int write_string(void *priv, mmbuffer_t *mb, int nbuf) { luaL_Buffer *buf = (luaL_Buffer *)priv; @@ -61,20 +125,14 @@ static int hunk_locations_cb(long start_a, long count_a, long start_b, long coun if (count_b > 0) { start_b += 1; } - - lua_State *lstate = (lua_State *)cb_data; - lua_createtable(lstate, 0, 0); - - lua_pushinteger(lstate, start_a); - lua_rawseti(lstate, -2, 1); - lua_pushinteger(lstate, count_a); - lua_rawseti(lstate, -2, 2); - lua_pushinteger(lstate, start_b); - lua_rawseti(lstate, -2, 3); - lua_pushinteger(lstate, count_b); - lua_rawseti(lstate, -2, 4); - - lua_rawseti(lstate, -2, (signed)lua_objlen(lstate, -2) + 1); + hunkpriv_t *priv = (hunkpriv_t *)cb_data; + lua_State *lstate = priv->lstate; + if (priv->linematch) { + get_linematch_results(lstate, priv->ma, priv->mb, start_a, count_a, start_b, count_b, + priv->iwhite); + } else { + lua_pushhunk(lstate, start_a, count_a, start_b, count_b); + } return 0; } @@ -149,7 +207,7 @@ static bool check_xdiff_opt(ObjectType actType, ObjectType expType, const char * } static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, xpparam_t *params, - Error *err) + bool *linematch, Error *err) { const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, err); @@ -205,6 +263,11 @@ static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, goto exit_1; } cfg->interhunkctxlen = v->data.integer; + } else if (strequal("linematch", k.data)) { + *linematch = api_object_to_bool(*v, "linematch", false, err); + if (ERROR_SET(err)) { + goto exit_1; + } } else { struct { const char *name; @@ -244,10 +307,8 @@ static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, if (had_on_hunk) { mode = kNluaXdiffModeOnHunkCB; - cfg->hunk_func = call_on_hunk_cb; } else if (had_result_type_indices) { mode = kNluaXdiffModeLocations; - cfg->hunk_func = hunk_locations_cb; } exit_1: @@ -268,6 +329,7 @@ int nlua_xdl_diff(lua_State *lstate) xdemitconf_t cfg; xpparam_t params; xdemitcb_t ecb; + bool linematch = false; CLEAR_FIELD(cfg); CLEAR_FIELD(params); @@ -280,7 +342,7 @@ int nlua_xdl_diff(lua_State *lstate) return luaL_argerror(lstate, 3, "expected table"); } - mode = process_xdl_diff_opts(lstate, &cfg, ¶ms, &err); + mode = process_xdl_diff_opts(lstate, &cfg, ¶ms, &linematch, &err); if (ERROR_SET(&err)) { goto exit_0; @@ -288,7 +350,7 @@ int nlua_xdl_diff(lua_State *lstate) } luaL_Buffer buf; - hunkpriv_t *priv = NULL; + hunkpriv_t priv; switch (mode) { case kNluaXdiffModeUnified: luaL_buffinit(lstate, &buf); @@ -296,14 +358,24 @@ int nlua_xdl_diff(lua_State *lstate) ecb.out_line = write_string; break; case kNluaXdiffModeOnHunkCB: - priv = xmalloc(sizeof(*priv)); - priv->lstate = lstate; - priv->err = &err; - ecb.priv = priv; + cfg.hunk_func = call_on_hunk_cb; + priv = (hunkpriv_t) { + .lstate = lstate, + .err = &err, + }; + ecb.priv = &priv; break; case kNluaXdiffModeLocations: + cfg.hunk_func = hunk_locations_cb; + priv = (hunkpriv_t) { + .lstate = lstate, + .ma = &ma, + .mb = &mb, + .linematch = linematch, + .iwhite = (params.flags & XDF_IGNORE_WHITESPACE) > 0 + }; + ecb.priv = &priv; lua_createtable(lstate, 0, 0); - ecb.priv = lstate; break; } @@ -314,8 +386,6 @@ int nlua_xdl_diff(lua_State *lstate) } } - XFREE_CLEAR(priv); - exit_0: if (ERROR_SET(&err)) { luaL_where(lstate, 1); -- cgit From f1c864cfe340dbb225caaf3dcbe28ee705be9f75 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 4 Nov 2022 10:31:09 +0000 Subject: fix(diff): remove size_t underflow (#20929) --- src/nvim/lua/xdiff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/lua/xdiff.c') diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index 428a33cdad..ec7dc3c666 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -60,8 +60,8 @@ static void get_linematch_results(lua_State *lstate, mmfile_t *ma, mmfile_t *mb, const char *diff_begin[2] = { ma->ptr, mb->ptr }; int diff_length[2] = { (int)count_a, (int)count_b }; - fastforward_buf_to_lnum(&diff_begin[0], (size_t)start_a); - fastforward_buf_to_lnum(&diff_begin[1], (size_t)start_b); + fastforward_buf_to_lnum(&diff_begin[0], start_a); + fastforward_buf_to_lnum(&diff_begin[1], start_b); int *decisions = NULL; size_t decisions_length = linematch_nbuffers(diff_begin, diff_length, 2, &decisions, iwhite); -- cgit From b854f2ce093de9593278b371de796f2ace044376 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 4 Nov 2022 11:12:17 +0000 Subject: fix(vim.diff): correctly apply hunk offsets with linematch (#20931) --- src/nvim/lua/xdiff.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/nvim/lua/xdiff.c') diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index ec7dc3c666..3adb6088fc 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -41,6 +41,15 @@ typedef struct { static void lua_pushhunk(lua_State *lstate, long start_a, long count_a, long start_b, long count_b) { + // Mimic extra offsets done by xdiff, see: + // src/xdiff/xemit.c:284 + // src/xdiff/xutils.c:(356,368) + if (count_a > 0) { + start_a += 1; + } + if (count_b > 0) { + start_b += 1; + } lua_createtable(lstate, 0, 0); lua_pushinteger(lstate, start_a); lua_rawseti(lstate, -2, 1); @@ -116,15 +125,6 @@ static int write_string(void *priv, mmbuffer_t *mb, int nbuf) // hunk_func callback used when opts.hunk_lines = true static int hunk_locations_cb(long start_a, long count_a, long start_b, long count_b, void *cb_data) { - // Mimic extra offsets done by xdiff, see: - // src/xdiff/xemit.c:284 - // src/xdiff/xutils.c:(356,368) - if (count_a > 0) { - start_a += 1; - } - if (count_b > 0) { - start_b += 1; - } hunkpriv_t *priv = (hunkpriv_t *)cb_data; lua_State *lstate = priv->lstate; if (priv->linematch) { -- cgit From 95f2f3cb5efcc18f17f2812ba6d1d9e1c06b2b5a Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 5 Nov 2022 00:58:01 +0000 Subject: fix(vim.diff): fix fastforward off-by-1 (#20937) --- src/nvim/lua/xdiff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/lua/xdiff.c') diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index 3adb6088fc..cd542b0e00 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -69,8 +69,8 @@ static void get_linematch_results(lua_State *lstate, mmfile_t *ma, mmfile_t *mb, const char *diff_begin[2] = { ma->ptr, mb->ptr }; int diff_length[2] = { (int)count_a, (int)count_b }; - fastforward_buf_to_lnum(&diff_begin[0], start_a); - fastforward_buf_to_lnum(&diff_begin[1], start_b); + fastforward_buf_to_lnum(&diff_begin[0], start_a + 1); + fastforward_buf_to_lnum(&diff_begin[1], start_b + 1); int *decisions = NULL; size_t decisions_length = linematch_nbuffers(diff_begin, diff_length, 2, &decisions, iwhite); -- cgit From 66360675cf4d091b7460e4a8e1435c13216c1929 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 11 Sep 2022 17:12:44 +0200 Subject: build: allow IWYU to fix includes for all .c files Allow Include What You Use to remove unnecessary includes and only include what is necessary. This helps with reducing compilation times and makes it easier to visualise which dependencies are actually required. Work on https://github.com/neovim/neovim/issues/549, but doesn't close it since this only works fully for .c files and not headers. --- src/nvim/lua/xdiff.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/nvim/lua/xdiff.c') diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c index cd542b0e00..857b159af5 100644 --- a/src/nvim/lua/xdiff.c +++ b/src/nvim/lua/xdiff.c @@ -1,19 +1,20 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include #include #include -#include -#include -#include +#include #include +#include "luaconf.h" +#include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/linematch.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" #include "nvim/lua/xdiff.h" +#include "nvim/macros.h" +#include "nvim/memory.h" #include "nvim/vim.h" #include "xdiff/xdiff.h" -- cgit