Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide context in the form of unchanged lines or AST nodes #744

Open
ds-cbo opened this issue Oct 6, 2023 · 1 comment
Open

provide context in the form of unchanged lines or AST nodes #744

ds-cbo opened this issue Oct 6, 2023 · 1 comment
Labels
enhancement New feature or request

Comments

@ds-cbo
Copy link

ds-cbo commented Oct 6, 2023

Is your feature request related to a problem? Please describe.
When using diffsitter as tool for git diff, line numbers don't make it immediately obvious where the change occurred.

Describe the solution you'd like
It would be nice if some surrounding context (3 lines before, 3 lines after) could be given, similar to how regular git diff and diff -C3 do it.

Describe alternatives you've considered
An alternative would be to allow machine-readable types of output (eg. json) for me or anyone else to write a new front-end around the logic of diffsitter.

Additional context
If it's not as obvious what counts as a line in AST-land, I would also be happy if I could get 10 AST nodes before and 10 AST nodes after the change (or some other configurable amount).

@0xdevalias
Copy link
Contributor

0xdevalias commented Jan 31, 2024

I think this, and providing the output in a more diff / git diff 'standard unified output' sort of a format would make these tool a LOT more useful for my needs.

As currently is, the output format is so newline/whitespace heavy and different from existing diff patterns that it's sort of painful to use (particularly over large files)

For example, using this repo (Ref), and this git config:

# https://github.com/afnanenayet/diffsitter
[difftool "diffsitter"]
  cmd = diffsitter "$LOCAL" "$REMOTE"

# https://github.com/afnanenayet/diffsitter
[difftool "diffsitter-debug"]
  cmd = diffsitter --debug "$LOCAL" "$REMOTE"

Here is the first 100 lines of output from a diff with diffsitter:

diffsitter
⇒ git difftool --tool diffsitter-debug 10d79cb6ed1dcefc36de84f4ce36a76ed3037d09~1 10d79cb6ed1dcefc36de84f4ce36a76ed3037d09 -- unpacked/_next/static/chunks/webpack.js > webpack.js-diffsitter.diff
 2024-01-31T03:32:29.788Z DEBUG diffsitter > Checking if /var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-kOCeQp/webpack.js can be parsed
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Deduced language "typescript" from extension "js" provided from user mappings
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Using tree-sitter parser for language typescript
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Succeeded loading grammar for typescript
 2024-01-31T03:32:29.788Z DEBUG diffsitter           > Checking if /var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-NsH9wd/webpack.js can be parsed
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Deduced language "typescript" from extension "js" provided from user mappings
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Using tree-sitter parser for language typescript
 2024-01-31T03:32:29.788Z INFO  libdiffsitter::parse > Succeeded loading grammar for typescript
 2024-01-31T03:32:29.788Z DEBUG diffsitter           > Extensions for both input files are supported
 2024-01-31T03:32:29.789Z DEBUG libdiffsitter        > Reading /var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-kOCeQp/webpack.js to string
 2024-01-31T03:32:29.789Z INFO  libdiffsitter        > Will deduce filetype from file extension
 2024-01-31T03:32:29.789Z INFO  libdiffsitter::parse > Deduced language "typescript" from extension "js" provided from user mappings
 2024-01-31T03:32:29.789Z INFO  libdiffsitter::parse > Using tree-sitter parser for language typescript
 2024-01-31T03:32:29.789Z INFO  libdiffsitter::parse > Succeeded loading grammar for typescript
 2024-01-31T03:32:29.789Z DEBUG libdiffsitter::parse > Constructed parser
 2024-01-31T03:32:29.795Z DEBUG libdiffsitter::parse > Parsed AST
 2024-01-31T03:32:29.795Z INFO  TimerFinished        > parse::parse_file(), Elapsed=6.671597ms
 2024-01-31T03:32:29.795Z DEBUG libdiffsitter        > Reading /var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-NsH9wd/webpack.js to string
 2024-01-31T03:32:29.795Z INFO  libdiffsitter        > Will deduce filetype from file extension
 2024-01-31T03:32:29.795Z INFO  libdiffsitter::parse > Deduced language "typescript" from extension "js" provided from user mappings
 2024-01-31T03:32:29.795Z INFO  libdiffsitter::parse > Using tree-sitter parser for language typescript
 2024-01-31T03:32:29.795Z INFO  libdiffsitter::parse > Succeeded loading grammar for typescript
 2024-01-31T03:32:29.795Z DEBUG libdiffsitter::parse > Constructed parser
 2024-01-31T03:32:29.798Z DEBUG libdiffsitter::parse > Parsed AST
 2024-01-31T03:32:29.798Z INFO  TimerFinished        > parse::parse_file(), Elapsed=3.05771ms
 2024-01-31T03:32:29.800Z INFO  TimerFinished        > ast::from_ts_tree(), Elapsed=1.473472ms
 2024-01-31T03:32:29.801Z INFO  TimerFinished        > ast::process(), Elapsed=2.954186ms
 2024-01-31T03:32:29.803Z INFO  TimerFinished        > ast::from_ts_tree(), Elapsed=1.841499ms
 2024-01-31T03:32:29.805Z INFO  TimerFinished        > ast::process(), Elapsed=3.629676ms
 2024-01-31T03:32:29.897Z INFO  TimerFinished        > diff::compute_edit_script(), Elapsed=92.026392ms
 2024-01-31T03:32:29.897Z INFO  libdiffsitter::render::unified > Using stack style horizontal for title

// ..snip..
/var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-kOCeQp/webpack.js -> /var/folders/j4/kxtq1cjs1l98xfqncjbsbx1c0000gn/T//git-blob-NsH9wd/webpack.js
============================================================================================================================================================

7:
--
-     f,

8 - 17:
-------
+     o,
+     f,
+     i,
+     d,
+     u,
+     b,
+     s = {},
+     l = {};
+   function p(e) {
+     var t = l[e];

11 - 14:
--------
-     i = {},
-     u = {};
-   function b(e) {
-     var t = u[e];

16:
---
-     var n = (u[e] = { id: e, loaded: !1, exports: {} }),

19:
---
+     var n = (l[e] = { id: e, loaded: !1, exports: {} }),

22:
---
+       s[e].call(n.exports, n, n.exports, p), (r = !1);

19:
---
-       i[e].call(n.exports, n, n.exports, b), (r = !1);

21:
---
-       r && delete u[e];

24:
---
+       r && delete l[e];

28 - 29:
--------
+   (p.m = s),
+     (p.amdD = function () {

25 - 26:
--------
-   (b.m = i),
-     (b.amdD = function () {

32:
---
+     (p.amdO = {}),

29:
---
-     (b.amdO = {}),

34:
---
+     (p.O = function (t, n, r, c) {

31:
---
-     (b.O = function (t, n, r, c) {

34 - 35:
--------
-         for (var f = e.length; f > 0 && e[f - 1][2] > c; f--) e[f] = e[f - 1];
-         e[f] = [n, r, c];

37 - 38:
--------
+         for (var a = e.length; a > 0 && e[a - 1][2] > c; a--) e[a] = e[a - 1];
+         e[a] = [n, r, c];

41:
---
+       for (var o = 1 / 0, a = 0; a < e.length; a++) {

38:
---
-       for (var a = 1 / 0, f = 0; f < e.length; f++) {

43 - 45:
--------
+           var n = e[a][0], r = e[a][1], c = e[a][2], f = !0, i = 0;
+           i < n.length;
+           i++

// ..snip (lines 101-867)..

Compare that to diffing the same file with a normal git diff:

git diff
⇒ git diff 10d79cb6ed1dcefc36de84f4ce36a76ed3037d09~1 10d79cb6ed1dcefc36de84f4ce36a76ed3037d09 -- unpacked/_next/static/chunks/webpack.js > webpack.js-git.diff
diff --git a/unpacked/_next/static/chunks/webpack.js b/unpacked/_next/static/chunks/webpack.js
index bd3fc07..bffcb59 100644
--- a/unpacked/_next/static/chunks/webpack.js
+++ b/unpacked/_next/static/chunks/webpack.js
@@ -5,58 +5,61 @@
     n,
     r,
     c,
-    f,
     a,
     o,
+    f,
+    i,
     d,
-    i = {},
-    u = {};
-  function b(e) {
-    var t = u[e];
+    u,
+    b,
+    s = {},
+    l = {};
+  function p(e) {
+    var t = l[e];
     if (void 0 !== t) return t.exports;
-    var n = (u[e] = { id: e, loaded: !1, exports: {} }),
+    var n = (l[e] = { id: e, loaded: !1, exports: {} }),
       r = !0;
     try {
-      i[e].call(n.exports, n, n.exports, b), (r = !1);
+      s[e].call(n.exports, n, n.exports, p), (r = !1);
     } finally {
-      r && delete u[e];
+      r && delete l[e];
     }
     return (n.loaded = !0), n.exports;
   }
-  (b.m = i),
-    (b.amdD = function () {
+  (p.m = s),
+    (p.amdD = function () {
       throw Error("define cannot be used indirect");
     }),
-    (b.amdO = {}),
+    (p.amdO = {}),
     (e = []),
-    (b.O = function (t, n, r, c) {
+    (p.O = function (t, n, r, c) {
       if (n) {
         c = c || 0;
-        for (var f = e.length; f > 0 && e[f - 1][2] > c; f--) e[f] = e[f - 1];
-        e[f] = [n, r, c];
+        for (var a = e.length; a > 0 && e[a - 1][2] > c; a--) e[a] = e[a - 1];
+        e[a] = [n, r, c];
         return;
       }
-      for (var a = 1 / 0, f = 0; f < e.length; f++) {
+      for (var o = 1 / 0, a = 0; a < e.length; a++) {
         for (
-          var n = e[f][0], r = e[f][1], c = e[f][2], o = !0, d = 0;
-          d < n.length;
-          d++
+          var n = e[a][0], r = e[a][1], c = e[a][2], f = !0, i = 0;
+          i < n.length;
+          i++
         )
-          a >= c &&
-          Object.keys(b.O).every(function (e) {
-            return b.O[e](n[d]);
+          o >= c &&
+          Object.keys(p.O).every(function (e) {
+            return p.O[e](n[i]);
           })
-            ? n.splice(d--, 1)
-            : ((o = !1), c < a && (a = c));
-        if (o) {
-          e.splice(f--, 1);
-          var i = r();
-          void 0 !== i && (t = i);
+            ? n.splice(i--, 1)
+            : ((f = !1), c < o && (o = c));
+        if (f) {
+          e.splice(a--, 1);
+          var d = r();
+          void 0 !== d && (t = d);
         }
       }
       return t;
     }),
-    (b.n = function (e) {
+    (p.n = function (e) {
       var t =
         e && e.__esModule
           ? function () {
@@ -65,7 +68,7 @@
           : function () {
               return e;
             };
-      return b.d(t, { a: t }), t;
+      return p.d(t, { a: t }), t;

// ..snip (lines 101-603)..

Contrasting the two diffs, not only is the git diff far more useful with the extra context/format; but it's ~264 lines shorter as well.

For a single line of diff change, diffsitter currently produces ~8 lines of output:

21:
---
-       r && delete u[e];

24:
---
+       r && delete l[e];

Compared to git diffs 2 (3 if you include a chunk header, more if you start including extra lines of context, but that then becomes an unfair comparison):

-      r && delete u[e];
+      r && delete l[e];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants