diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/command_callback/test_phpcs_command_callback.vader | 29 | ||||
-rw-r--r-- | test/completion/test_completion_events.vader | 36 | ||||
-rw-r--r-- | test/completion/test_lsp_completion_messages.vader | 6 | ||||
-rw-r--r-- | test/completion/test_omnifunc_completion.vader | 12 | ||||
-rw-r--r-- | test/completion/test_public_completion_api.vader | 21 | ||||
-rw-r--r-- | test/fixers/test_pgformatter_fixer_callback.vader | 24 | ||||
-rw-r--r-- | test/handler/test_checkstyle_handler.vader | 8 | ||||
-rw-r--r-- | test/lsp/test_did_save_event.vader | 1 | ||||
-rw-r--r-- | test/lsp/test_engine_lsp_response_handling.vader (renamed from test/test_engine_lsp_response_handling.vader) | 168 | ||||
-rw-r--r-- | test/test_ale_info_to_clipboard.vader | 15 | ||||
-rw-r--r-- | test/test_history_saving.vader | 3 | ||||
-rw-r--r-- | test/test_ignoring_linters.vader | 12 |
12 files changed, 265 insertions, 70 deletions
diff --git a/test/command_callback/test_phpcs_command_callback.vader b/test/command_callback/test_phpcs_command_callback.vader index e5d2f449..48a599e4 100644 --- a/test/command_callback/test_phpcs_command_callback.vader +++ b/test/command_callback/test_phpcs_command_callback.vader @@ -11,25 +11,36 @@ Execute(The local phpcs executable should be used): let g:executable = ale#path#Simplify(g:dir . '/../phpcs-test-files/project-with-phpcs/vendor/bin/phpcs') - AssertLinter g:executable, - \ ale#Escape(g:executable) . ' -s --report=emacs --stdin-path=%s' + AssertLinter g:executable, ale#path#BufferCdString(bufnr('')) + \ . ale#Escape(g:executable) + \ . ' -s --report=emacs --stdin-path=%s' Execute(use_global should override local executable detection): let g:ale_php_phpcs_use_global = 1 call ale#test#SetFilename('../phpcs-test-files/project-with-phpcs/foo/test.php') - AssertLinter 'phpcs', - \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s' + AssertLinter 'phpcs', ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('phpcs') + \ . ' -s --report=emacs --stdin-path=%s' Execute(Projects without local executables should use the global one): call ale#test#SetFilename('../phpcs-test-files/project-without-phpcs/foo/test.php') - AssertLinter 'phpcs', - \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s' + AssertLinter 'phpcs', ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('phpcs') + \ . ' -s --report=emacs --stdin-path=%s' -Execute(User provided options are used): +Execute(User provided options should be used): let g:ale_php_phpcs_options = '--my-user-provided-option my-value' - AssertLinter 'phpcs', - \ ale#Escape('phpcs') . ' -s --report=emacs --stdin-path=%s --my-user-provided-option my-value' + AssertLinter 'phpcs', ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('phpcs') + \ . ' -s --report=emacs --stdin-path=%s --my-user-provided-option my-value' + +Execute(The _standard option should be used): + let g:ale_php_phpcs_standard = 'foobar' + + AssertLinter 'phpcs', ale#path#BufferCdString(bufnr('')) + \ . ale#Escape('phpcs') + \ . ' -s --report=emacs --stdin-path=%s --standard=' . ale#Escape('foobar') diff --git a/test/completion/test_completion_events.vader b/test/completion/test_completion_events.vader index ebdcb5df..6bc0035e 100644 --- a/test/completion/test_completion_events.vader +++ b/test/completion/test_completion_events.vader @@ -57,8 +57,6 @@ After: unlet! b:ale_old_omnifunc unlet! b:ale_old_completeopt unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_completion_result unlet! b:ale_complete_done_time @@ -136,7 +134,7 @@ Execute(ale#completion#Show() should remember the omnifunc setting and replace i let &l:omnifunc = 'FooBar' let b:ale_completion_info = {'source': 'ale-automatic'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual 'FooBar', b:ale_old_omnifunc AssertEqual 'ale#completion#AutomaticOmniFunc', &l:omnifunc @@ -149,7 +147,7 @@ Execute(ale#completion#Show() should remember the completeopt setting and replac let &l:completeopt = 'menu' let b:ale_completion_info = {'source': 'ale-automatic'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual 'menu', b:ale_old_completeopt AssertEqual 'menu,menuone,noselect,noinsert', &l:completeopt @@ -162,7 +160,7 @@ Execute(ale#completion#Show() should set the preview option if it's set): let &l:completeopt = 'menu,preview' let b:ale_completion_info = {'source': 'ale-automatic'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual 'menu,preview', b:ale_old_completeopt AssertEqual 'menu,menuone,preview,noselect,noinsert', &l:completeopt @@ -176,7 +174,7 @@ Execute(ale#completion#Show() should not replace the completeopt setting for man let &l:completeopt = 'menu,preview' - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) Assert !exists('b:ale_old_completeopt') @@ -204,7 +202,7 @@ Execute(ale#completion#AutomaticOmniFunc() should set the preview option if it's Execute(ale#completion#Show() should make the correct feedkeys() call for automatic completion): let b:ale_completion_info = {'source': 'ale-automatic'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual [], g:feedkeys_calls sleep 1ms @@ -212,7 +210,7 @@ Execute(ale#completion#Show() should make the correct feedkeys() call for automa Execute(ale#completion#Show() should make the correct feedkeys() call for manual completion): let b:ale_completion_info = {'source': 'ale-automatic'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual [], g:feedkeys_calls sleep 1ms @@ -220,7 +218,7 @@ Execute(ale#completion#Show() should make the correct feedkeys() call for manual Execute(ale#completion#Show() should not call feedkeys() for other sources): let b:ale_completion_info = {'source': 'deoplete'} - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) sleep 1ms AssertEqual [], g:feedkeys_calls @@ -229,20 +227,22 @@ Execute(ale#completion#Show() shouldn't do anything if you switch back to normal let &l:completeopt = 'menu,preview' let g:fake_mode = 'n' - call ale#completion#Show('Response', 'Parser') + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) AssertEqual 'menu,preview', &l:completeopt Assert !exists('b:ale_old_omnifunc') Assert !exists('b:ale_old_completeopt') - Assert !exists('b:ale_completion_response') - Assert !exists('b:ale_completion_parser') + Assert !exists('b:ale_completion_result') AssertEqual [], g:feedkeys_calls -Execute(ale#completion#Show() should set up the response and parser): - call ale#completion#Show('Response', 'Parser') +Execute(ale#completion#Show() should save the result it is given): + call ale#completion#Show([]) + + AssertEqual [], b:ale_completion_result + + call ale#completion#Show([{'word': 'x', 'kind': 'v', 'icase': 1}]) - AssertEqual 'Response', b:ale_completion_response - AssertEqual 'Parser', b:ale_completion_parser + AssertEqual [{'word': 'x', 'kind': 'v', 'icase': 1}], b:ale_completion_result Execute(ale#completion#Done() should restore old omnifunc values): let b:ale_old_omnifunc = 'FooBar' @@ -317,8 +317,6 @@ Execute(b:ale_completion_info should be set up correctly when requesting complet Execute(b:ale_completion_info should be set up correctly for other sources): let b:ale_completion_result = [] - let b:ale_completion_response = [] - let b:ale_completion_parser = 'type' call setpos('.', [bufnr(''), 3, 14, 0]) call ale#completion#GetCompletions('deoplete') @@ -334,8 +332,6 @@ Execute(b:ale_completion_info should be set up correctly for other sources): \ }, \ b:ale_completion_info Assert !exists('b:ale_completion_result') - Assert !exists('b:ale_completion_response') - Assert !exists('b:ale_completion_parser') Execute(The correct keybinds should be configured): redir => g:output diff --git a/test/completion/test_lsp_completion_messages.vader b/test/completion/test_lsp_completion_messages.vader index 25536436..9598e5f0 100644 --- a/test/completion/test_lsp_completion_messages.vader +++ b/test/completion/test_lsp_completion_messages.vader @@ -69,8 +69,6 @@ After: unlet! b:ale_old_omnifunc unlet! b:ale_old_completeopt unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_complete_done_time unlet! b:ale_linters unlet! b:ale_tsserver_completion_names @@ -246,14 +244,14 @@ Execute(Two completion requests shouldn't be sent in a row): \ 'lsp': 'stdio', \ 'executable': 'foo', \ 'command': 'foo', - \ 'project_root_callback': {-> '/foo/bar'}, + \ 'project_root': {-> '/foo/bar'}, \}) call ale#linter#Define('python', { \ 'name': 'bar', \ 'lsp': 'stdio', \ 'executable': 'foo', \ 'command': 'foo', - \ 'project_root_callback': {-> '/foo/bar'}, + \ 'project_root': {-> '/foo/bar'}, \}) let b:ale_linters = ['foo', 'bar'] diff --git a/test/completion/test_omnifunc_completion.vader b/test/completion/test_omnifunc_completion.vader index 221d337f..3711f974 100644 --- a/test/completion/test_omnifunc_completion.vader +++ b/test/completion/test_omnifunc_completion.vader @@ -1,7 +1,5 @@ Before: unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_completion_result let b:lsp_started = 0 @@ -12,27 +10,19 @@ Before: return b:lsp_started endfunction - function! Identity(x) abort - return a:x - endfunction - function! SetCompletionResult(...) abort let b:ale_completion_result = ['foo'] endfunction function! SetCompletionResponse(...) abort - let b:ale_completion_response = ['foo'] - let b:ale_completion_parser = 'Identity' + let b:ale_completion_result = ['foo'] endfunction After: unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_completion_result unlet! b:lsp_started - delfunction Identity delfunction SetCompletionResult delfunction SetCompletionResponse diff --git a/test/completion/test_public_completion_api.vader b/test/completion/test_public_completion_api.vader index d4db2d6f..befbb436 100644 --- a/test/completion/test_public_completion_api.vader +++ b/test/completion/test_public_completion_api.vader @@ -3,42 +3,21 @@ Before: unlet! b:ale_linters unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_completion_result - function! Identity(x) abort - return a:x - endfunction - After: - delfunction Identity - call ale#linter#Reset() unlet! b:ale_linters unlet! b:ale_completion_info - unlet! b:ale_completion_response - unlet! b:ale_completion_parser unlet! b:ale_completion_result Execute(ale#completion#GetCompletionResult() should return v:null when there are no results): AssertEqual v:null, ale#completion#GetCompletionResult() -Execute(ale#completion#GetCompletionResult() should parse the result when it has yet to be parsed): - let b:ale_completion_response = [1] - let b:ale_completion_parser = 'Identity' - - AssertEqual [1], ale#completion#GetCompletionResult() - Assert !exists('b:ale_completion_response') - Assert !exists('b:ale_completion_parser') - AssertEqual [1], b:ale_completion_result - Execute(ale#completion#GetCompletionResult() should return a result computed previously): let b:ale_completion_result = [1] - Assert !exists('b:ale_completion_response') - Assert !exists('b:ale_completion_parser') AssertEqual [1], ale#completion#GetCompletionResult() Execute(ale#completion#GetCompletionPosition() should return 0 when there is no completion information): diff --git a/test/fixers/test_pgformatter_fixer_callback.vader b/test/fixers/test_pgformatter_fixer_callback.vader new file mode 100644 index 00000000..5baa6f6f --- /dev/null +++ b/test/fixers/test_pgformatter_fixer_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:ale_sql_pgformatter_executable + Save g:ale_sql_pgformatter_options + +After: + Restore + +Execute(The pgFormatter callback should return the correct default values): + AssertEqual + \ { + \ 'command': ale#Escape('pg_format') + \ }, + \ ale#fixers#pgformatter#Fix(bufnr('')) + +Execute(The pgFormatter executable and options should be configurable): + let g:ale_sql_pgformatter_executable = '/path/to/pg_format' + let g:ale_sql_pgformatter_options = '-n' + + AssertEqual + \ { + \ 'command': ale#Escape('/path/to/pg_format') + \ . ' -n', + \ }, + \ ale#fixers#pgformatter#Fix(bufnr('')) diff --git a/test/handler/test_checkstyle_handler.vader b/test/handler/test_checkstyle_handler.vader index 218fe344..c60bbc82 100644 --- a/test/handler/test_checkstyle_handler.vader +++ b/test/handler/test_checkstyle_handler.vader @@ -21,10 +21,18 @@ Execute(The checkstyle handler should parse lines correctly): \ 'code': 'JavadocMethod', \ 'type': 'W', \ }, + \ { + \ 'lnum': 11, + \ 'col': 7, + \ 'text': 'WhitespaceAround: ''if'' is not followed by whitespace.', + \ 'code': 'WhitespaceAround', + \ 'type': 'W', + \ }, \ ], \ ale_linters#java#checkstyle#Handle(666, [ \ '[WARN] whatever:101: ''method def rcurly'' has incorrect indentation level 4, expected level should be 2. [Indentation]', \ '[WARN] whatever:63:3: Missing a Javadoc comment. [JavadocMethod]', + \ '[WARN] whatever:11:7: WhitespaceAround: ''if'' is not followed by whitespace. [WhitespaceAround]', \ ]) Execute(The checkstyle handler should parse lines from older checkstyle versions correctly): diff --git a/test/lsp/test_did_save_event.vader b/test/lsp/test_did_save_event.vader index 1a60bc9f..bdea6d98 100644 --- a/test/lsp/test_did_save_event.vader +++ b/test/lsp/test_did_save_event.vader @@ -9,6 +9,7 @@ Before: call ale#test#SetFilename('dummy.txt') runtime autoload/ale/lsp.vim + runtime autoload/ale/lsp_linter.vim let g:ale_disable_lsp = 0 unlet! b:ale_disable_lsp diff --git a/test/test_engine_lsp_response_handling.vader b/test/lsp/test_engine_lsp_response_handling.vader index 84febe39..9abfa087 100644 --- a/test/test_engine_lsp_response_handling.vader +++ b/test/lsp/test_engine_lsp_response_handling.vader @@ -1,19 +1,42 @@ Before: + Save g:ale_set_lists_synchronously Save g:ale_buffer_info Save g:ale_lsp_error_messages + Save g:ale_set_loclist + Save g:ale_set_signs + Save g:ale_set_quickfix + Save g:ale_set_highlights + Save g:ale_echo_cursor + Save g:ale_disable_lsp + Save g:ale_history_enabled + Save g:ale_history_log_output + let g:ale_disable_lsp = 0 + let g:ale_set_lists_synchronously = 1 let g:ale_buffer_info = {} + let g:ale_set_loclist = 1 + " Disable features we don't need for these tests. + let g:ale_set_signs = 0 + let g:ale_set_quickfix = 0 + let g:ale_set_highlights = 0 + let g:ale_echo_cursor = 0 + let g:ale_history_enabled = 1 + let g:ale_history_log_output = 1 unlet! g:ale_lsp_error_messages unlet! b:ale_linters + unlet! b:ale_disable_lsp + call ale#linter#Reset() call ale#test#SetDirectory('/testplugin/test') + call setloclist(0, []) After: Restore unlet! b:ale_linters + call setloclist(0, []) call ale#test#RestoreDirectory() call ale#linter#Reset() call ale#lsp_linter#ClearLSPData() @@ -92,6 +115,35 @@ Execute(tsserver syntax error responses should be handled correctly): \ ], \ ale#test#GetLoclistWithoutModule() + " Syntax errors on the project root should not populate the LocList. + call ale#lsp_linter#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'syntaxDiag', + \ 'body': { + \ 'file': g:dir, + \ 'diagnostics':[ + \ { + \ 'start': { + \ 'line':2, + \ 'offset':14, + \ }, + \ 'end': { + \ 'line':2, + \ 'offset':15, + \ }, + \ 'text': ''','' expected.', + \ "code":1005 + \ }, + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ ], + \ ale#test#GetLoclistWithoutModule() + Execute(tsserver semantic error responses should be handled correctly): runtime ale_linters/typescript/tsserver.vim call ale#test#SetFilename('filename.ts') @@ -165,6 +217,35 @@ Execute(tsserver semantic error responses should be handled correctly): \ ], \ ale#test#GetLoclistWithoutModule() + " Semantic errors on the project root should not populate the LocList. + call ale#lsp_linter#HandleLSPResponse(1, { + \ 'seq': 0, + \ 'type': 'event', + \ 'event': 'semanticDiag', + \ 'body': { + \ 'file': g:dir, + \ 'diagnostics':[ + \ { + \ 'start': { + \ 'line':2, + \ 'offset':14, + \ }, + \ 'end': { + \ 'line':2, + \ 'offset':15, + \ }, + \ 'text': 'Some semantic error', + \ "code":1005 + \ }, + \ ], + \ }, + \}) + + AssertEqual + \ [ + \ ], + \ ale#test#GetLoclistWithoutModule() + Execute(tsserver errors should mark tsserver no longer active): let b:ale_linters = ['tsserver'] runtime ale_linters/typescript/tsserver.vim @@ -186,6 +267,93 @@ Execute(tsserver errors should mark tsserver no longer active): AssertEqual [], g:ale_buffer_info[bufnr('')].active_linter_list +Execute(LSP diagnostics responses should be handled correctly): + let b:ale_linters = ['eclipselsp'] + runtime ale_linters/java/eclipselsp.vim + call ale#test#SetFilename('filename.java') + call ale#engine#InitBufferInfo(bufnr('')) + call ale#lsp_linter#SetLSPLinterMap({'1': 'eclipselsp'}) + + call ale#lsp_linter#HandleLSPResponse(1, { + \ 'jsonrpc':'2.0', + \ 'method':'textDocument/publishDiagnostics', + \ 'params': { + \ 'uri':'file://' . g:dir . '/filename.java', + \ 'diagnostics': [ + \ { + \ 'range': { + \ 'start': { + \ 'line': 0, + \ 'character':0 + \ }, + \ 'end': { + \ 'line': 0, + \ 'character':0 + \ } + \ }, + \ 'severity': 2, + \ 'code': "", + \ 'source': 'Java', + \ 'message': 'Missing JRE 1-8' + \ } + \ ] + \ } + \}) + + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'bufnr': bufnr(''), + \ 'col': 1, + \ 'pattern': '', + \ 'valid': 1, + \ 'vcol': 0, + \ 'nr': -1, + \ 'type': 'W', + \ 'text': 'Missing JRE 1-8' + \ } + \ ], + \ ale#test#GetLoclistWithoutModule() + +Execute(LSP diagnostics responses on project root should not populate loclist): + let b:ale_linters = ['eclipselsp'] + runtime ale_linters/java/eclipselsp.vim + call ale#test#SetFilename('filename.java') + call ale#engine#InitBufferInfo(bufnr('')) + call ale#lsp_linter#SetLSPLinterMap({'1': 'eclipselsp'}) + + call ale#lsp_linter#HandleLSPResponse(1, { + \ 'jsonrpc':'2.0', + \ 'method':'textDocument/publishDiagnostics', + \ 'params': { + \ 'uri':'file://' . g:dir, + \ 'diagnostics': [ + \ { + \ 'range': { + \ 'start': { + \ 'line': 0, + \ 'character':0 + \ }, + \ 'end': { + \ 'line': 0, + \ 'character':0 + \ } + \ }, + \ 'severity': 2, + \ 'code': "", + \ 'source': 'Java', + \ 'message': 'Missing JRE 1-8' + \ } + \ ] + \ } + \}) + + AssertEqual + \ [ + \ ], + \ ale#test#GetLoclistWithoutModule() + Execute(LSP errors should mark linters no longer active): let b:ale_linters = ['pyls'] runtime ale_linters/python/pyls.vim diff --git a/test/test_ale_info_to_clipboard.vader b/test/test_ale_info_to_clipboard.vader new file mode 100644 index 00000000..2014a310 --- /dev/null +++ b/test/test_ale_info_to_clipboard.vader @@ -0,0 +1,15 @@ +After: + unlet! g:output + +Execute(ALEInfoToClipboard should that clipboard support is required): + " When run in the Docker image, there's no clipboard support, so this test + " will actually run. + if !has('clipboard') + let g:output = '' + + redir => g:output + :ALEInfoToClipboard + redir END + + AssertEqual 'clipboard not available. Try :ALEInfoToFile instead.', join(split(g:output)) + endif diff --git a/test/test_history_saving.vader b/test/test_history_saving.vader index 18b64db5..5d81c2a3 100644 --- a/test/test_history_saving.vader +++ b/test/test_history_saving.vader @@ -1,5 +1,6 @@ Before: Save g:ale_max_buffer_history_size + Save g:ale_history_enabled Save g:ale_history_log_output Save g:ale_run_synchronously Save g:ale_enabled @@ -54,8 +55,6 @@ After: " Reset the shell back to what it was before. let &shell = g:current_shell unlet g:current_shell - let g:ale_history_enabled = 1 - let g:ale_history_log_output = 0 unlet g:history call ale#engine#Cleanup(bufnr('')) diff --git a/test/test_ignoring_linters.vader b/test/test_ignoring_linters.vader index f2e9e5c9..d758af5c 100644 --- a/test/test_ignoring_linters.vader +++ b/test/test_ignoring_linters.vader @@ -1,3 +1,11 @@ +Before: + Save g:ale_disable_lsp + +After: + Restore + + unlet! b:ale_disable_lsp + Execute(GetList should ignore some invalid values): AssertEqual [], ale#engine#ignore#GetList('', 'foo') AssertEqual [], ale#engine#ignore#GetList('', 0) @@ -98,7 +106,6 @@ Execute(Exclude should handle Dictionaries): \ ) Execute(Exclude should filter LSP linters when g:ale_disable_lsp is set to 1): - let g:ale_disable_lsp = 1 AssertEqual \ [ \ {'name': 'linter1', 'aliases': [], 'lsp': ''}, @@ -116,7 +123,6 @@ Execute(Exclude should filter LSP linters when g:ale_disable_lsp is set to 1): \ ) Execute(Exclude should filter LSP linters when b:ale_disable_lsp is set to 1): - let b:ale_disable_lsp = 1 AssertEqual \ [ \ {'name': 'linter1', 'aliases': [], 'lsp': ''}, @@ -351,7 +357,7 @@ Execute(ale_disable_lsp should be applied for tsserver): AssertEqual [], g:loclist -Execute(ale_disable_lsp should be applied for LSP linters): +Execute(ale_disable_lsp should be applied for LSP linters): call ale#test#SetFilename('filename.py') call ale#engine#InitBufferInfo(bufnr('')) call ale#lsp_linter#SetLSPLinterMap({'347': 'lsplinter'}) |