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

json-parse-error \u0000 is not allowed without JSON_ALLOW_NUL #2681

Closed
snyball opened this issue Mar 6, 2021 · 23 comments
Closed

json-parse-error \u0000 is not allowed without JSON_ALLOW_NUL #2681

snyball opened this issue Mar 6, 2021 · 23 comments

Comments

@snyball
Copy link

snyball commented Mar 6, 2021

Describe the bug
Certain C++ files produce the following window popup warning message:

with message (json-parse-error \u0000 is not allowed without JSON_ALLOW_NUL <string> 1 14613 14613)

To Reproduce
Clone the https://github.com/snyball/Hawck master branch, and open the src/LuaUtils.h file.

Expected behavior
Did not expect to get that warning.

Which Language Server did you use
ccls

OS
Linux.

@yyoncho
Copy link
Member

yyoncho commented Mar 6, 2021

open the src/LuaUtils.h file.

I dont see that file.

@yyoncho
Copy link
Member

yyoncho commented Mar 6, 2021

Ok, I found that there is LuaUtils.hpp, investigating...

@yyoncho
Copy link
Member

yyoncho commented Mar 6, 2021

Can you share what version of emacs do you use and what server? I am unable to repro with emacs 27.1 and clangd.

@snyball
Copy link
Author

snyball commented Mar 6, 2021

Happens with the ccls server (reproduced on versions 0.20201025 and 0.20201219-3,) I'm using Emacs 28 from the native-comp branch and emacs-lsp from commit c3cbadc.

@madscientist
Copy link
Contributor

I've seen this same error with some source files, with ccls. I haven't tried to determine if I can reproduce it with the same set of files, after restarting Emacs / clearing the ccls cache. There is, definitely, no actual nul character in the source files. I don't know if this is an error in the ccls server (or the llvm parser) or if it's on the Emacs side. I'm using Emacs 27.1 / lsp-mode 20210223 / ccls 0.20201025

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

I would expect this to be a ccls bug.

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

@snyball can you tell what you did to cause that issue? I.e. where was your cursor? If this can be reproduced reliably, we could find out where in ccls this is caused using lsp-print-io and an upstream PR could be made.

@snyball
Copy link
Author

snyball commented Mar 7, 2021

@nbfalcon I don't know exactly what I'm doing in particular to cause the bug other than opening the file, then I get the warning. I also get it every other second when moving around the file.

You could try setting lsp-idle-delay to a low value, then start moving the cursor downwards from the beginning of the file, for me that produces a whole bunch of these errors.

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

@snyball I have lsp-idle-delay set to 0, and moving my cursor trough the buffer doesn't show the warning. I have experienced it myself, though. What verison of ccls are you running?

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

For reference, I use

$ ccls --version
ccls version 0.20201219-2-ga2d2fd81
clang version 10.0.0-4ubuntu1 

@orlandini
Copy link

I am facing the same issue. If it would be useful, I could provide the repo containing the file that is triggering this same behaviour.

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

@orlandini can you reliably reproduce this? I believe it would be insanely helpful if we could get an lsp-print-io log when that is issue occurs.

@orlandini
Copy link

Yes, it does happen everytime I open this file in a buffer. Would you please tell me how to generate this log? I can do it right away.

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

@orlandini type M-: (setq lsp-print-io t). Thanks a lot!

@nbfalcon
Copy link
Member

nbfalcon commented Mar 7, 2021

You will find the result in *lsp-log: <server>:<pid>*.

@yyoncho
Copy link
Member

yyoncho commented Mar 7, 2021

@orlandini can you reliably reproduce this? I believe it would be insanely helpful if we could get an lsp-print-io log when that is issue occurs.

I don't think that it will show up here because we print the IO after deserializing it in order to pretty-print it.

@orlandini you may try M-x trace-function RET json-parse-string

@yyoncho
Copy link
Member

yyoncho commented Mar 7, 2021

The alternative is to capture the input/output outside of emacs, something like this - #843 (comment)

@orlandini
Copy link

After (setq lsp-print-io t) and opening the file I get:
lsp-log:

Command "ccls" is present on the path.
Command "clangd --header-insertion-decorators=0" is not present on the path.
Command "ccls" is present on the path.
Command "clangd --header-insertion-decorators=0" is not present on the path.
Found the following clients for /home/orlandini/git/pzsuite/neopz-src/Util/tpzautopointer.h: (server-id ccls, priority 0)
The following clients were selected based on priority: (server-id ccls, priority 0)

lsp-log: ccls:1952936:

[Trace - 06:52:18 ] Sending request 'textDocument/codeAction - (13940)'.
Params: {
  "textDocument": {
    "uri": "file:///home/orlandini/git/pzsuite/neopz-src/Util/tpzautopointer.h"
  },
  "range": {
    "start": {
      "line": 37,
      "character": 0
    },
    "end": {
      "line": 37,
      "character": 0
    }
  },
  "context": {
    "diagnostics": []
  }
}


[Trace - 06:52:18 ] Received response 'textDocument/codeAction - (13940)' in 68ms.
Result: []


[Trace - 06:52:19 ] Sending request 'textDocument/documentSymbol - (13941)'.
Params: {
  "textDocument": {
    "uri": "file:///home/orlandini/git/pzsuite/neopz-src/Util/tpzautopointer.h"
  }
}


[Trace - 06:52:19 ] Sending request 'textDocument/codeAction - (13942)'.
Params: {
  "textDocument": {
    "uri": "file:///home/orlandini/git/pzsuite/neopz-src/Util/tpzautopointer.h"
  },
  "range": {
    "start": {
      "line": 37,
      "character": 0
    },
    "end": {
      "line": 37,
      "character": 0
    }
  },
  "context": {
    "diagnostics": []
  }
}


[Trace - 06:52:19 ] Sending request 'textDocument/documentLink - (13943)'.
Params: {
  "textDocument": {
    "uri": "file:///home/orlandini/git/pzsuite/neopz-src/Util/tpzautopointer.h"
  }
}


[Trace - 06:52:19 ] Received response 'textDocument/codeAction - (13942)' in 83ms.
Result: []


[Trace - 06:52:19 ] Received response 'textDocument/documentLink - (13943)' in 82ms.
Result: [
  {
    "target": "file:///usr/include/c%2B%2B/9/mutex",
    "range": {
      "end": {
        "character": 15,
        "line": 8
      },
      "start": {
        "character": 10,
        "line": 8
      }
    }
  },
  {
    "target": "file:///usr/include/c%2B%2B/9/stdlib.h",
    "range": {
      "end": {
        "character": 18,
        "line": 42
      },
      "start": {
        "character": 10,
        "line": 42
      }
    }
  }
]

When doing M-x trace-function RET json-parse-string I get:

======================================================================
1 -> (json-parse-string "{\"jsonrpc\":\"2.0\",\"id\":13944,\"result\":[]}" :object-type hash-table :null-object nil :false-object nil)
1 <- json-parse-string: #s(hash-table size 3 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("jsonrpc" "2.0" "id" 13944 "result" []))
======================================================================
1 -> (json-parse-string "{\"jsonrpc\":\"2.0\",\"id\":13945,\"result\":[{\"name\":\"TPZAUTOPOINTER_H\",\"detail\":\"TPZAUTOPOINTER_H\",\"kind\":255,\"range\":{\"start\":{\"line\":6,\"character\":8},\"end\":{\"line\":6,\"character\":24}},\"selectionRange\":{\"start\":{\"line\":6,\"character\":8},\"end\":{\"line\":6,\"character\":24}},\"children\":[]},{\"name\":\"AP_MUTEX_ARRAY_SZ\",\"detail\":\"AP_MUTEX_ARRAY_SZ\",\"kind\":255,\"range\":{\"start\":{\"line\":18,\"character\":8},\"end\":{\"line\":18,\"character\":29}},\"selectionRange\":{\"start\":{\"line\":18,\"character\":8},\"end\":{\"line\":18,\"character\":25}},\"children\":[]},{\"name\":\"AP_MUTEX_HASH_1\",\"detail\":\"AP_MUTEX_HASH_1\",\"kind\":255,\"range\":{\"start\":{\"line\":20,\"character\":8},\"end\":{\"line\":25,\"character\":41}},\"selectionRange\":{\"start\":{\"line\":20,\"character\":8},\"end\":{\"line\":20,\"character\":23}},\"children\":[]},{\"name\":\"AP_MUTEX_HASH_2\",\"detail\":\"AP_MUTEX_HASH_2\",\"kind\":255,\"range\":{\"start\":{\"line\":27,\"character\":8},\"end\":{\"line\":30,\"character\":41}},\"selectionRange\":{\"start\":{\"line\":27,\"character\":8},\"end\":{\"line\":27,\"character\":23}},\"children\":[]},{\"name\":\"gAutoPointerMutexArray\",\"detail\":\"extern std::mutex gAutoPointerMutexArray[]\",\"kind\":13,\"range\":{\"start\":{\"line\":32,\"character\":0},\"end\":{\"line\":32,\"character\":42}},\"selectionRange\":{\"start\":{\"line\":32,\"character\":18},\"end\":{\"line\":32,\"character\":40}},\"children\":[]},{\"name\":\"get_ap_mutex\",\"detail\":\"inline std::mutex *get_ap_mutex(void *obj)\",\"kind\":12,\"range\":{\"start\":{\"line\":33,\"character\":0},\"end\":{\"line\":40,\"character\":1}},\"selectionRange\":{\"start\":{\"line\":33,\"character\":19},\"end\":{\"line\":33,\"character\":31}},\"children\":[]},{\"name\":\"TPZAutoPointer\",\"detail\":\"class TPZAutoPointer {}\",\"kind\":5,\"range\":{\"start\":{\"line\":51,\"character\":0},\"end\":{\"line\":235,\"character\":1}},\"selectionRange\":{\"start\":{\"line\":51,\"character\":6},\"end\":{\"line\":51,\"character\":20}},\"children\":[{\"name\":\"TPZReference\",\"detail\":\"struct TPZAutoPointer::TPZReference {}\",\"kind\":23,\"range\":{\"start\":{\"line\":55,\"character\":4},\"end\":{\"line\":130,\"character\":5}},\"selectionRange\":{\"start\":{\"line\":55,\"character\":11},\"end\":{\"line\":55,\"character\":23}},\"children\":[{\"name\":\"fPointer\",\"detail\":\"T2 *TPZAutoPointer::TPZReference::fPointer\",\"kind\":8,\"range\":{\"start\":{\"line\":58,\"character\":8},\"end\":{\"line\":58,\"character\":20}},\"selectionRange\":{\"start\":{\"line\":58,\"character\":12},\"end\":{\"line\":58,\"character\":20}},\"children\":[]},{\"name\":\"fCounter\",\"detail\":\"int *TPZAutoPointer::TPZReference::fCounter\",\"kind\":8,\"range\":{\"start\":{\"line\":59,\"character\":8},\"end\":{\"line\":59,\"character\":21}},\"selectionRange\":{\"start\":{\"line\":59,\"character\":13},\"end\":{\"line\":59,\"character\":21}},\"children\":[]},{\"name\":\"TPZReference<T2>\",\"detail\":\"TPZAutoPointer::TPZReference::TPZReference<T2>()\",\"kind\":9,\"range\":{\"start\":{\"line\":61,\"character\":8},\"end\":{\"line\":66,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":61,\"character\":8},\"end\":{\"line\":61,\"character\":20}},\"children\":[]},{\"name\":\"TPZReference<T2>\",\"detail\":\"TPZAutoPointer::TPZReference::TPZReference<T2>(T2 *pointer)\",\"kind\":9,\"range\":{\"start\":{\"line\":68,\"character\":8},\"end\":{\"line\":73,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":68,\"character\":8},\"end\":{\"line\":68,\"character\":20}},\"children\":[]},{\"name\":\"~TPZReference<T2>\",\"detail\":\"TPZAutoPointer::TPZReference::~TPZReference<T2>()\",\"kind\":6,\"range\":{\"start\":{\"line\":75,\"character\":8},\"end\":{\"line\":85,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":75,\"character\":8},\"end\":{\"line\":75,\"character\":21}},\"children\":[]},{\"name\":\"ReallocForNuma\",\"detail\":\"void TPZAutoPointer::TPZReference::ReallocForNuma(int node_id)\",\"kind\":6,\"range\":{\"start\":{\"line\":87,\"character\":8},\"end\":{\"line\":100,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":87,\"character\":13},\"end\":{\"line\":87,\"character\":27}},\"children\":[]},{\"name\":\"Increment\",\"detail\":\"bool TPZAutoPointer::TPZReference::Increment()\",\"kind\":6,\"range\":{\"start\":{\"line\":104,\"character\":8},\"end\":{\"line\":111,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":104,\"character\":13},\"end\":{\"line\":104,\"character\":22}},\"children\":[]},{\"name\":\"Decrease\",\"detail\":\"bool TPZAutoPointer::TPZReference::Decrease()\",\"kind\":6,\"range\":{\"start\":{\"line\":113,\"character\":8},\"end\":{\"line\":128,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":113,\"character\":13},\"end\":{\"line\":113,\"character\":21}},\"children\":[]}]},{\"name\":\"fRef\",\"detail\":\"TPZReference<T> *TPZAutoPointer::fRef\",\"kind\":8,\"range\":{\"start\":{\"line\":133,\"character\":1},\"end\":{\"line\":133,\"character\":22}},\"selectionRange\":{\"start\":{\"line\":133,\"character\":18},\"end\":{\"line\":133,\"character\":22}},\"children\":[]},{\"name\":\"TPZAutoPointer<T>\",\"detail\":\"TPZAutoPointer::TPZAutoPointer<T>()\",\"kind\":9,\"range\":{\"start\":{\"line\":137,\"character\":1},\"end\":{\"line\":140,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":137,\"character\":1},\"end\":{\"line\":137,\"character\":15}},\"children\":[]},{\"name\":\"~TPZAutoPointer<T>\",\"detail\":\"TPZAutoPointer::~TPZAutoPointer<T>()\",\"kind\":6,\"range\":{\"start\":{\"line\":143,\"character\":1},\"end\":{\"line\":148,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":143,\"character\":1},\"end\":{\"line\":143,\"character\":16}},\"children\":[]},{\"name\":\"TPZAutoPointer<T>\",\"detail\":\"TPZAutoPointer::TPZAutoPointer<T>(T *obj)\",\"kind\":9,\"range\":{\"start\":{\"line\":151,\"character\":1},\"end\":{\"line\":154,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":151,\"character\":1},\"end\":{\"line\":151,\"character\":15}},\"children\":[]},{\"name\":\"TPZAutoPointer<T>\",\"detail\":\"TPZAutoPointer::TPZAutoPointer<T>(const TPZAutoPointer<T> &copy)\",\"kind\":9,\"range\":{\"start\":{\"line\":157,\"character\":1},\"end\":{\"line\":161,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":157,\"character\":1},\"end\":{\"line\":157,\"character\":15}},\"children\":[]},{\"name\":\"operator=\",\"detail\":\"TPZAutoPointer<T> &TPZAutoPointer::operator=(TPZAutoPointer<T> &&copy)\",\"kind\":6,\"range\":{\"start\":{\"line\":164,\"character\":1},\"end\":{\"line\":171,\"character\":9}},\"selectionRange\":{\"start\":{\"line\":164,\"character\":17},\"end\":{\"line\":164,\"character\":26}},\"children\":[]},{\"name\":\"operator=\",\"detail\":\"TPZAutoPointer<T> &TPZAutoPointer::operator=(const TPZAutoPointer<T> &copy)\",\"kind\":6,\"range\":{\"start\":{\"line\":174,\"character\":1},\"end\":{\"line\":181,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":174,\"character\":17},\"end\":{\"line\":174,\"character\":26}},\"children\":[]},{\"name\":\"operator T &()\\u0000virtual int TP\",\"detail\":\"operator T &()\",\"kind\":6,\"range\":{\"start\":{\"line\":184,\"character\":1},\"end\":{\"line\":187,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":184,\"character\":1},\"end\":{\"line\":184,\"character\":12}},\"children\":[]},{\"name\":\"operator*\",\"detail\":\"T &TPZAutoPointer::operator*() const\",\"kind\":6,\"range\":{\"start\":{\"line\":190,\"character\":1},\"end\":{\"line\":193,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":190,\"character\":4},\"end\":{\"line\":190,\"character\":14}},\"children\":[]},{\"name\":\"operator*\",\"detail\":\"T &TPZAutoPointer::operator*()\",\"kind\":6,\"range\":{\"start\":{\"line\":196,\"character\":1},\"end\":{\"line\":199,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":196,\"character\":4},\"end\":{\"line\":196,\"character\":14}},\"children\":[]},{\"name\":\"operator->\",\"detail\":\"T *TPZAutoPointer::operator->() const\",\"kind\":6,\"range\":{\"start\":{\"line\":202,\"character\":1},\"end\":{\"line\":205,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":202,\"character\":4},\"end\":{\"line\":202,\"character\":14}},\"children\":[]},{\"name\":\"operator->\",\"detail\":\"T *TPZAutoPointer::operator->()\",\"kind\":6,\"range\":{\"start\":{\"line\":206,\"character\":1},\"end\":{\"line\":209,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":206,\"character\":4},\"end\":{\"line\":206,\"character\":14}},\"children\":[]},{\"name\":\"ReallocForNuma\",\"detail\":\"void TPZAutoPointer::ReallocForNuma(int node)\",\"kind\":6,\"range\":{\"start\":{\"line\":211,\"character\":1},\"end\":{\"line\":214,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":211,\"character\":6},\"end\":{\"line\":211,\"character\":20}},\"children\":[]},{\"name\":\"operator bool\",\"detail\":\"TPZAutoPointer::operator bool() const\",\"kind\":6,\"range\":{\"start\":{\"line\":217,\"character\":1},\"end\":{\"line\":219,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":217,\"character\":1},\"end\":{\"line\":217,\"character\":14}},\"children\":[]},{\"name\":\"operator bool\",\"detail\":\"TPZAutoPointer::operator bool()\",\"kind\":6,\"range\":{\"start\":{\"line\":220,\"character\":1},\"end\":{\"line\":222,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":220,\"character\":1},\"end\":{\"line\":220,\"character\":14}},\"children\":[]},{\"name\":\"Count\",\"detail\":\"int TPZAutoPointer::Count() const\",\"kind\":6,\"range\":{\"start\":{\"line\":225,\"character\":1},\"end\":{\"line\":228,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":225,\"character\":5},\"end\":{\"line\":225,\"character\":10}},\"children\":[]},{\"name\":\"Count\",\"detail\":\"int TPZAutoPointer::Count()\",\"kind\":6,\"range\":{\"start\":{\"line\":229,\"character\":1},\"end\":{\"line\":232,\"character\":2}},\"selectionRange\":{\"start\":{\"line\":229,\"character\":5},\"end\":{\"line\":229,\"character\":10}},\"children\":[]}]},{\"name\":\"TPZAutoPointerDynamicCast\",\"detail\":\"TPZAutoPointer<R> TPZAutoPointerDynamicCast(TPZAutoPointer<T2> in)\",\"kind\":12,\"range\":{\"start\":{\"line\":234,\"character\":4},\"end\":{\"line\":234,\"character\":77}},\"selectionRange\":{\"start\":{\"line\":234,\"character\":29},\"end\":{\"line\":234,\"character\":54}},\"children\":[]},{\"name\":\"TPZAutoPointerDynamicCast\",\"detail\":\"TPZAutoPointer<R> TPZAutoPointerDynamicCast(TPZAutoPointer<T> in)\",\"kind\":12,\"range\":{\"start\":{\"line\":238,\"character\":0},\"end\":{\"line\":248,\"character\":1}},\"selectionRange\":{\"start\":{\"line\":238,\"character\":18},\"end\":{\"line\":238,\"character\":43}},\"children\":[]}]}" :object-type hash-table :null-object nil :false-object nil)
1 <- json-parse-string: !non-local\ exit!
======================================================================
1 -> (json-parse-string "{\"jsonrpc\":\"2.0\",\"id\":13946,\"result\":[]}" :object-type hash-table :null-object nil :false-object nil)
1 <- json-parse-string: #s(hash-table size 3 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("jsonrpc" "2.0" "id" 13946 "result" []))
======================================================================
1 -> (json-parse-string "{\"jsonrpc\":\"2.0\",\"id\":13947,\"result\":[{\"range\":{\"start\":{\"line\":8,\"character\":10},\"end\":{\"line\":8,\"character\":15}},\"target\":\"file:///usr/include/c%2B%2B/9/mutex\"},{\"range\":{\"start\":{\"line\":42,\"character\":10},\"end\":{\"line\":42,\"character\":18}},\"target\":\"file:///usr/include/c%2B%2B/9/stdlib.h\"}]}" :object-type hash-table :null-object nil :false-object nil)
1 <- json-parse-string: #s(hash-table size 3 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("jsonrpc" "2.0" "id" 13947 "result" [#s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("range" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("start" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 8 "character" 10)) "end" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 8 "character" 15)))) "target" "file:///usr/include/c%2B%2B/9/mutex")) #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("range" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("start" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 42 "character" 10)) "end" #s(hash-table size 2 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 42 "character" 18)))) "target" "file:///usr/include/c%2B%2B/9/stdlib.h"))]))
======================================================================
1 -> (json-parse-string "{\"jsonrpc\":\"2.0\",\"id\":13948,\"result\":[]}" :object-type hash-table :null-object nil :false-object nil)
1 <- json-parse-string: #s(hash-table size 3 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("jsonrpc" "2.0" "id" 13948 "result" []))

This happens as soon as I open the file.

@yyoncho
Copy link
Member

yyoncho commented Mar 8, 2021

AFAICS the problematic element is "operator T &()virtual int TP", it has \u0000 before it. Can you check if there is something related to that element that might be causing this symbol to be returned? To me, it looks like a server issue bug generally at emacs side we can handle better that kind of strings but we(at lsp-mode side) are limited by the fact that 'json-parse-string is in the core.

Meanwhile, the following snippet will fix the issue:

(advice-add 'json-parse-string :around 
            (lambda (orig string &rest rest)
              (apply orig (s-replace "\\u0000" "" string)
                     rest)))

@nbfalcon
Copy link
Member

nbfalcon commented Mar 8, 2021

A minimal example that triggers this issue, either with imenu or using lsp-treemacs-symbols:

template <class T> struct Q { T n; };

struct X {
  template <class T> operator Q<T>() {}
};

The bug seems to be caused by template cast operators, and I suspect it is an issue with ccls' interning code. This is definitely a ccls bug. Here is the json:

{
  "jsonrpc": "2.0",
  "id": 21242,
  "result": [
    {
      "name": "Q",
      "detail": "struct Q {}",
      "kind": 23,
      "range": {
        "start": {
          "line": 0,
          "character": 19
        },
        "end": {
          "line": 0,
          "character": 36
        }
      },
      "selectionRange": {
        "start": {
          "line": 0,
          "character": 26
        },
        "end": {
          "line": 0,
          "character": 27
        }
      },
      "children": [
        {
          "name": "n",
          "detail": "T Q::n",
          "kind": 8,
          "range": {
            "start": {
              "line": 0,
              "character": 30
            },
            "end": {
              "line": 0,
              "character": 33
            }
          },
          "selectionRange": {
            "start": {
              "line": 0,
              "character": 32
            },
            "end": {
              "line": 0,
              "character": 33
            }
          },
          "children": []
        }
      ]
    },
    {
      "name": "X",
      "detail": "struct X {}",
      "kind": 23,
      "range": {
        "start": {
          "line": 2,
          "character": 0
        },
        "end": {
          "line": 4,
          "character": 1
        }
      },
      "selectionRange": {
        "start": {
          "line": 2,
          "character": 7
        },
        "end": {
          "line": 2,
          "character": 8
        }
      },
      "children": [
        {
          "name": "operator Q<T>()\u0000struct Q {}\u0000T ",
          "detail": "operator Q<T>()",
          "kind": 6,
          "range": {
            "start": {
              "line": 3,
              "character": 21
            },
            "end": {
              "line": 3,
              "character": 39
            }
          },
          "selectionRange": {
            "start": {
              "line": 3,
              "character": 21
            },
            "end": {
              "line": 3,
              "character": 34
            }
          },
          "children": []
        }
      ]
    }
  ]
}

@yyoncho
Copy link
Member

yyoncho commented Mar 8, 2021

@nbfalcon thank you.

Closing the bug. Please report it in ccls repo and/or use the solution from #2681 (comment)

@adimit
Copy link

adimit commented Aug 15, 2022

Meanwhile, the following snippet will fix the issue:

(advice-add 'json-parse-string :around 
            (lambda (orig string &rest rest)
              (apply orig (s-replace "\\u0000" "" string)
                     rest)))

Just leaving this here in case anyone stumbles over it: ts-ls has the same problem, as of version 1.0.0 of typescript-language-server. However, patching json-parse-string will not properly work around it, as the problem occurs during lsp--create-filter-function, which uses lsp-json-read-buffer, which in turn relies on the natively compiled json-parse-buffer (not json-parse-string). So you need to patch the latter, too:

  (advice-add 'json-parse-buffer :around
              (lambda (orig &rest rest)
                (while (re-search-forward "\\u0000" nil t)
                  (replace-match ""))
                (apply orig rest)))

This worked around the issue for me on Emacs 28. According to @ktfleming in typescript-language-server/typescript-language-server#559, Emacs 29 should fix the issue, but I haven't confirmed that myself. Here's a complete workaround, though it might be somewhat inefficent.

vincentbernat added a commit to vincentbernat/homemanager-configuration that referenced this issue Nov 20, 2022
This is a common issue with LSP servers and patching this from inside
Emacs (by advising parsing functions) is highly inefficient. See:

- emacs-lsp/lsp-mode#2681 (comment)
- typescript-language-server/typescript-language-server#559 (comment)
- https://github.com/jadestrong/lsp-volar#hacks

The patch is extracted from Emacs 29.
@ghost
Copy link

ghost commented Apr 7, 2023

To add to @adimit 's solution, I had both to double escape the backslash, and add save-excursion (because 'json-parse-buffer fails if cursor is not at the start of the buffer):

(advice-add 'json-parse-buffer :around
              (lambda (orig &rest rest)
                (save-excursion
                  (while (re-search-forward "\\\\u0000" nil t)
                    (replace-match "")))
                (apply orig rest)))

(Otherwise, it just removes u0000, but leaves the backslash symbol, still causing a json parse error).

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

No branches or pull requests

6 participants