Skip to content

Commit 8a7c1fc

Browse files
authored
Merge pull request #375 from jakejx/native-json-parsing
Use native JSON parsing when available
2 parents bb508ad + b364395 commit 8a7c1fc

File tree

4 files changed

+138
-15
lines changed

4 files changed

+138
-15
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,6 @@ this variable to non-nil value for Javascript buffers using `setq-local` macro.
345345

346346
How long to wait after user input before highlighting the current identifier.
347347

348+
##### tide-native-json-parsing `nil`
349+
350+
Use the native JSON functions for encoding and decoding.

test/test.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"files": [
3+
"./lib/cli.ts",
4+
"./lib/index.ts",
5+
"./test/indexSpec.ts",
6+
"./typings/bundle.d.ts",
7+
"./typings/empower/empower.d.ts",
8+
"./typings/gulp/gulp.d.ts",
9+
"./typings/mocha/mocha.d.ts",
10+
"./typings/node/node.d.ts",
11+
"./typings/orchestrator/orchestrator.d.ts",
12+
"./typings/power-assert-formatter/power-assert-formatter.d.ts",
13+
"./typings/power-assert/power-assert.d.ts",
14+
"./typings/q/Q.d.ts",
15+
"./node_modules/typescript/lib/lib.es6.d.ts"
16+
],
17+
"exclude": [],
18+
"filesGlob": [
19+
"./**/*.ts",
20+
"./**/*.tsx",
21+
"!./**/*.d.ts",
22+
"!./gulpfile.ts",
23+
"./typings/**/*.d.ts",
24+
"!./node_modules/**/*.ts",
25+
"./node_modules/typescript/lib/lib.es6.d.ts"
26+
],
27+
"compilerOptions": {
28+
"noEmitOnError": true,
29+
"newLine": "LF",
30+
"listFiles": true,
31+
"sourceMap": true,
32+
"rootDir": ".",
33+
"experimentalDecorators": true,
34+
"removeComments": true,
35+
"noImplicitAny": true,
36+
"declaration": true,
37+
"module": "commonjs",
38+
"target": "es5"
39+
}
40+
}

tide-tests.el

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,61 @@ file that uses tabs for indentation."
432432
"a")))
433433
(delete-process (tide-current-server))
434434
(kill-buffer buffer)))
435-
436-
(provide 'tide-tests)
435+
(when (>= emacs-major-version 27)
436+
(ert-deftest test-tide-safe-json-read-file ()
437+
"Test that `tide-safe-json-read-file' produces the same output for both json.el and the native json parser"
438+
(let ((native-output
439+
(let ((tide-native-json-parsing t))
440+
(tide-safe-json-read-file "test/test.json")))
441+
(elisp-output
442+
(let ((tide-native-json-parsing nil))
443+
(tide-safe-json-read-file "test/test.json"))))
444+
(should (equal native-output elisp-output)))))
445+
446+
(when (>= emacs-major-version 27)
447+
(ert-deftest test-tide-safe-json-read-string ()
448+
"Test that `tide-safe-json-read-string' produces the same output for both native and elisp JSON libraries"
449+
(let* ((test-json
450+
(with-temp-buffer
451+
(insert-file-contents "test/test.json")
452+
(buffer-string)))
453+
(native-output
454+
(let ((tide-native-json-parsing t))
455+
(tide-safe-json-read-string test-json)))
456+
(elisp-output
457+
(let ((tide-native-json-parsing nil))
458+
(tide-safe-json-read-string test-json))))
459+
(should (equal native-output elisp-output)))))
460+
461+
(when (>= emacs-major-version 27)
462+
(ert-deftest test-tide-json-read-object ()
463+
"Test that `tide-json-read-object' produces the same output for both native and elisp JSON libraries"
464+
(let* ((native-output
465+
(with-temp-buffer
466+
(insert-file-contents "test/test.json")
467+
(let ((tide-native-json-parsing t))
468+
(tide-json-read-object))))
469+
(elisp-output
470+
(with-temp-buffer
471+
(insert-file-contents "test/test.json")
472+
(let ((tide-native-json-parsing nil))
473+
(tide-json-read-object)))))
474+
(should (equal native-output elisp-output)))))
475+
476+
(when (>= emacs-major-version 27)
477+
(ert-deftest test-tide-json-encode ()
478+
"Test that `tide-json-read-object' produces the same JSON string for both native and elisp libraries"
479+
(let* ((json-obj `(:number 123
480+
:string "string"
481+
:true t
482+
:false ,json-false
483+
:array [(:number 123 :string "string" :true t :false ,json-false)]))
484+
(native-string (let ((tide-native-json-parsing t))
485+
(tide-json-encode json-obj)))
486+
(elisp-string (let ((tide-native-json-parsing nil))
487+
(tide-json-encode json-obj))))
488+
(should (equal native-string elisp-string))))
489+
490+
(provide 'tide-tests))
437491

438492
;;; tide-tests.el ends here

tide.el

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,15 @@ this variable to non-nil value for Javascript buffers using `setq-local' macro."
239239
:group 'tide
240240
:safe #'booleanp)
241241

242+
(defcustom tide-native-json-parsing (and (>= emacs-major-version 27)
243+
(functionp 'json-serialize)
244+
(functionp 'json-parse-buffer)
245+
(functionp 'json-parse-string)
246+
nil)
247+
"Use native JSON parsing (only emacs >= 27)."
248+
:type 'boolean
249+
:group 'tide)
250+
242251
(defconst tide--minimal-emacs
243252
"24.4"
244253
"This is the oldest version of Emacs that tide supports.")
@@ -336,16 +345,36 @@ buffers, as they don't set `buffer-file-name' correctly."
336345

337346
(defun tide-safe-json-read-file (filename)
338347
(condition-case nil
339-
(let ((json-object-type 'plist))
340-
(json-read-file filename))
348+
(if tide-native-json-parsing
349+
(with-temp-buffer
350+
(insert-file-contents filename)
351+
(goto-char (point-min))
352+
(json-parse-buffer :object-type 'plist :null-object json-null :false-object json-false))
353+
(let ((json-object-type 'plist))
354+
(json-read-file filename)))
341355
(error '())))
342356

343357
(defun tide-safe-json-read-string (string)
344358
(condition-case nil
345-
(let ((json-object-type 'plist))
346-
(json-read-from-string string))
359+
(if tide-native-json-parsing
360+
(json-parse-string string :object-type 'plist :null-object json-null :false-object json-false)
361+
(let ((json-object-type 'plist))
362+
(json-read-from-string string)))
347363
(error '())))
348364

365+
(defun tide-json-read-object ()
366+
(if tide-native-json-parsing
367+
(json-parse-buffer :object-type 'plist :null-object json-null :false-object json-false :array-type 'list)
368+
(let ((json-object-type 'plist)
369+
(json-array-type 'list))
370+
(json-read-object))))
371+
372+
(defun tide-json-encode (obj)
373+
"Encode OBJ into a JSON string. JSON arrays must be represented with vectors."
374+
(if tide-native-json-parsing
375+
(json-serialize obj :null-object json-null :false-object json-false)
376+
(json-encode obj)))
377+
349378
(defun tide-plist-get (list &rest args)
350379
(cl-reduce
351380
(lambda (object key)
@@ -591,7 +620,7 @@ Offset is one based."
591620
(let* ((request-id (tide-next-request-id))
592621
(command `(:command ,name :seq ,request-id :arguments ,args))
593622
(json-encoding-pretty-print nil)
594-
(encoded-command (json-encode command))
623+
(encoded-command (tide-json-encode command))
595624
(payload (concat encoded-command "\n")))
596625
(process-send-string (tide-current-server) payload)
597626
(when callback
@@ -814,9 +843,7 @@ Currently, two kinds of cleanups are done:
814843

815844
(defun tide-decode-response (process)
816845
(with-current-buffer (process-buffer process)
817-
(let ((length (tide-decode-response-legth))
818-
(json-object-type 'plist)
819-
(json-array-type 'list))
846+
(let ((length (tide-decode-response-legth)))
820847
(when (and length (tide-enough-response-p length))
821848
(search-forward "{")
822849
(backward-char 1)
@@ -828,7 +855,7 @@ Currently, two kinds of cleanups are done:
828855
`(:success :json-false :type "response"
829856
:message ,tide-max-response-length-error-message
830857
:request_seq ,seq)))
831-
(json-read-object))))
858+
(tide-json-read-object))))
832859
(delete-region (point-min) (point))
833860
(when response
834861
(tide-dispatch response)))
@@ -1263,7 +1290,7 @@ Noise can be anything like braces, reserved keywords, etc."
12631290
`(:file ,(tide-buffer-file-name)
12641291
:startLine ,(tide-line-number-at-pos) :startOffset ,(tide-current-offset)
12651292
:endLine ,(tide-line-number-at-pos) :endOffset ,(+ 1 (tide-current-offset))
1266-
:errorCodes ,(tide-get-flycheck-errors-ids-at-point))))
1293+
:errorCodes ,(vconcat (tide-get-flycheck-errors-ids-at-point)))))
12671294

12681295
(defun tide-command:getCombinedCodeFix (fixId)
12691296
(tide-send-command-sync "getCombinedCodeFix"
@@ -1561,7 +1588,7 @@ This function is used for the basic completions sorting."
15611588
(let* ((source (plist-get (get-text-property 0 'completion name) :source))
15621589
(entry-names (if source
15631590
`(:entryNames [(:name ,name :source ,source)])
1564-
`(:entryNames (,name))))
1591+
`(:entryNames [,name])))
15651592
(arguments (-concat (get-text-property 0 'file-location name)
15661593
entry-names)))
15671594
(-when-let (response (tide-send-command-sync "completionEntryDetails" arguments))
@@ -2439,12 +2466,11 @@ current buffer."
24392466
t))
24402467

24412468
;;; Identifier highlighting
2442-
24432469
(defun tide-command:documentHighlights (cb)
24442470
(tide-send-command
24452471
"documentHighlights"
24462472
`(:file ,(tide-buffer-file-name) :line ,(tide-line-number-at-pos) :offset ,(tide-current-offset)
2447-
:filesToSearch (,(tide-buffer-file-name)))
2473+
:filesToSearch [,(tide-buffer-file-name)])
24482474
cb))
24492475

24502476
(defface tide-hl-identifier-face

0 commit comments

Comments
 (0)