commit 2f886ac8d31505bf759b5ed17f9a0a1ce650d8af
parent b6c895c75fa91083025507ae6146bbc1372b4cd6
Author: Tomas Nemec <nemi@skaut.cz>
Date: Fri, 29 Apr 2022 10:12:52 +0200
update
Diffstat:
8 files changed, 141 insertions(+), 285 deletions(-)
diff --git a/after/plugin/nulls.lua b/after/plugin/nulls.lua
@@ -1,75 +1,59 @@
-local servers = require('tms.lsp.servers')
-
-local on_attach = function(client, bufnr)
- local lsp = vim.lsp
-
- lsp.handlers['textDocument/hover'] = lsp.with(lsp.handlers.hover, { border = 'single' })
- lsp.handlers['textDocument/signatureHelp'] = lsp.with(lsp.handlers.signature_help, { border = 'single' })
- vim.api.nvim_buf_set_option(bufnr, 'tagfunc', 'v:lua.vim.lsp.tagfunc')
- -- vim.api.nvim_buf_set_option(bufnr, 'formatexpr', 'v:lua.vim.lsp.formatexpr()')
-
- local opts = function(desc) return { silent = true, buffer = bufnr, desc = desc } end
- vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts('LSP Definition'))
- vim.keymap.set('n', 'gD', '<cmd>vsplit | lua vim.lsp.buf.definition()<cr>', opts('LSP definition in vsplit'))
- vim.keymap.set('n', 'gT', vim.lsp.buf.type_definition, opts('LSP Type Definition'))
- vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts('LSP Implementation'))
- vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts('LSP Hover'))
- vim.keymap.set('n', '<c-p>', vim.lsp.buf.signature_help, opts('LSP Signature Help'))
- vim.keymap.set('i', '<c-p>', vim.lsp.buf.signature_help, opts('LSP Signature Help'))
- vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts('LSP References'))
- vim.keymap.set('n', 'ga', vim.lsp.buf.code_action, opts('LSP Code Actions'))
- vim.keymap.set('v', 'ga', vim.lsp.buf.range_code_action, opts('LSP Code Actions'))
- vim.keymap.set('n', 'gn', vim.lsp.buf.rename, opts('LSP Rename'))
-
- vim.keymap.set('n', 'Q', vim.lsp.buf.formatting, opts('LSP Format'))
- vim.keymap.set('v', 'Q', ':<c-u>lua vim.lsp.buf.range_formatting()<cr>', opts('LSP Range Format'))
-
- local has_lsp_format, lsp_format = pcall(require, 'lsp-format')
- if has_lsp_format then lsp_format.on_attach(client) end
- local has_aerial, aerial = pcall(require, 'aerial')
- if has_aerial then aerial.on_attach(client, bufnr) end
-end
-
-local capabilities = function()
- local ok, cnl = pcall(require, 'cmp_nvim_lsp')
- if ok then
- return cnl.update_capabilities(vim.lsp.protocol.make_client_capabilities())
- else
- return vim.lsp.protocol.make_client_capabilities()
- end
-end
-
-local make_opts = function(name, server)
- local opts = {}
- opts.on_attach = on_attach
- opts.capabilities = capabilities()
- opts = servers.setup(name, opts, server)
- return opts
-end
-
-local setup = function()
- -- LSP Installer
- local has_lspi, lsp_installer = pcall(require, 'nvim-lsp-installer')
- if has_lspi then
- lsp_installer.on_server_ready(function(server)
- local opts = make_opts(server.name, server)
- server:setup(opts)
- end)
- end
-
- -- LSP Config
- local has_lspc, lsp_config = pcall(require, 'lspconfig')
- if has_lspc then
- local manual_servers = { 'gdscript', 'dartls' }
- for _, name in ipairs(manual_servers) do
- local opts = make_opts(name)
- lsp_config[name].setup(opts)
- end
- end
-
- -- Manual
- local has_zk, zk = pcall(require, 'zk')
- if has_zk then zk.setup({ lsp = { config = make_opts('zk') } }) end
-end
-
-return { on_attach = on_attach, setup = setup }
+if not pcall(require, 'null-ls') then return end
+
+local null_ls = require('null-ls')
+local h = require('null-ls.helpers')
+local builtins = null_ls.builtins
+
+local zsh_diag = {
+ name = 'zsh check',
+ method = null_ls.methods.DIAGNOSTICS,
+ filetypes = { 'zsh' },
+ update_on_insert = true,
+ generator = null_ls.generator({
+ command = 'zsh',
+ args = { '-n', '$FILENAME' },
+ format = 'line',
+ check_exit_code = function(code) return code <= 1 end,
+ from_stderr = true,
+ to_stdin = true,
+ on_output = h.diagnostics.from_patterns({ { pattern = [[%w+:(%d+): (.*)]], groups = { 'row', 'message' } } }),
+ }),
+}
+
+null_ls.setup({
+ on_attach = function(client, bufnr) require('tms.lsp').on_attach(client, bufnr) end,
+ sources = {
+ -- formatting
+ builtins.formatting.prettier.with {
+ filetypes = { 'html', 'yaml', 'markdown', 'css', 'scss' },
+ args = h.range_formatting_args_factory({
+ '--parser',
+ vim.api.nvim_buf_get_option(0, 'filetype'),
+ '--stdin-filepath',
+ '$FILENAME',
+ }, '--range-start', '--range-end'),
+ },
+ builtins.formatting.prettier.with {
+ filetypes = { 'typescript' },
+ args = h.range_formatting_args_factory({
+ '--parser',
+ vim.api.nvim_buf_get_option(0, 'filetype'),
+ '--trailing-comma',
+ 'all',
+ '--tab-width',
+ '2',
+ '--stdin-filepath',
+ '$FILENAME',
+ }, '--range-start', '--range-end'),
+ },
+ builtins.formatting.lua_format,
+ -- builtins.formatting.clang_format,
+ builtins.formatting.shfmt.with {
+ filetypes = { 'sh', 'zsh' },
+ args = { '-i', vim.opt.shiftwidth:get(), '-filename', '$FILENAME' },
+ },
+ -- diagnostic
+ builtins.diagnostics.shellcheck,
+ zsh_diag,
+ },
+})
diff --git a/ftplugin/dart.lua b/ftplugin/dart.lua
@@ -1,38 +1,41 @@
vim.g.dart_style_guide = 2
vim.g.dart_html_in_string = true
-local dlsp = require('tms.ft.dart.lsp')
+local has_helper, helper = pcall(require, 'dartls-helper.lsp')
+if not has_helper then return end
+
+local lsp = require('dartls-helper.lsp')
+local req = require('dartls-helper.request')
+
local ddebug = require('tms.ft.dart.debug')
local analyze = require('tms.ft.dart.analyze')
-local cmd_opts = { buffer = nil }
+local cmd_opts = {}
-- vim.cmd [[command! -buffer DartAnalyzer lua require('tms.ft.dart.analyze').qf2131()]]
-vim.api.nvim_create_user_command('DartDebug', ddebug.func, cmd_opts)
-vim.api.nvim_create_user_command('DartPrint', ddebug.print, cmd_opts)
-vim.api.nvim_create_user_command('DartOrganizeImports', dlsp.organize_imports, cmd_opts)
-vim.api.nvim_create_user_command('DartFixAll', dlsp.fix_all, cmd_opts)
-vim.api.nvim_create_user_command('DartExtract', dlsp.extract_method, cmd_opts)
-vim.api.nvim_create_user_command('DartVariable', dlsp.extract_local_variable, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartDebug', ddebug.func, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartPrint', ddebug.print, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartOrganizeImports', lsp.organize_imports, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartFixAll', lsp.fix_all, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartExtract', lsp.extract_method, cmd_opts)
+vim.api.nvim_buf_create_user_command(0, 'DartVariable', lsp.extract_local_variable, cmd_opts)
local opts = function(desc) return { buffer = true, noremap = true, desc = desc } end
vim.keymap.set('n', '<leader>pp', function() ddebug.print() end, opts('Dart Debug Print'))
vim.keymap.set('n', '<leader>pn', function() analyze.qf2131() end, opts('Dart Analyze'))
-vim.keymap.set('n', '<leader>po', dlsp.organize_imports, opts('Dart Organize Imports'))
-vim.keymap.set('n', '<leader>pf', function() dlsp.fix_all() end, opts('Dart Fix All'))
-vim.keymap.set({ 'v', 'n' }, '<leader>pi', dlsp.inline_local_variable, opts('Dart Inline Local Varibale'))
-vim.keymap.set({ 'v', 'n' }, '<leader>pe', dlsp.extract_local_variable, opts('Dart Extract Local Varibale'))
-vim.keymap.set({ 'v', 'n' }, '<leader>pm', dlsp.extract_method, opts('Dart Extract Method'))
-vim.keymap.set('n', '<leader>pl', dlsp.list_code_action_kinds, opts('Dart List Code Actions'))
-vim.keymap.set('n', '<leader>ps', function() dlsp.execute_code_action('refactor.splitVariableDeclaration') end, opts('Dart Split Variable Declaration'))
-vim.keymap.set('n', '<leader>pj', function() dlsp.execute_code_action('refactor.joinVariableDeclaration') end, opts('Dart Join Variable Declaration'))
-vim.keymap.set('n', '<leader>px', function() dlsp.execute_code_action('refactor.convert.bodyToExpression') end, opts('Dart Convert To Expression'))
-vim.keymap.set('n', '<leader>pa', function() dlsp.execute_code_action('refactor.convert.bodyToAsync') end, opts('Dart Convert To Async'))
-vim.keymap.set('n', '<leader>pb', function() dlsp.execute_code_action('refactor.convert.bodyToBlock') end, opts('Dart Convert To Block'))
+vim.keymap.set('n', '<leader>po', lsp.organize_imports, opts('Dart Organize Imports'))
+vim.keymap.set('n', '<leader>pf', function() lsp.fix_all() end, opts('Dart Fix All'))
+vim.keymap.set({ 'v', 'n' }, '<leader>pi', lsp.inline_local_variable, opts('Dart Inline Local Varibale'))
+vim.keymap.set({ 'v', 'n' }, '<leader>pe', lsp.extract_local_variable, opts('Dart Extract Local Varibale'))
+vim.keymap.set({ 'v', 'n' }, '<leader>pm', lsp.extract_method, opts('Dart Extract Method'))
+vim.keymap.set('n', '<leader>pl', lsp.list_code_action_kinds, opts('Dart List Code Actions'))
+vim.keymap.set('n', '<leader>ps', function() req.execute_code_action('refactor.splitVariableDeclaration') end, opts('Dart Split Variable Declaration'))
+vim.keymap.set('n', '<leader>pj', function() req.execute_code_action('refactor.joinVariableDeclaration') end, opts('Dart Join Variable Declaration'))
+vim.keymap.set('n', '<leader>px', function() req.execute_code_action('refactor.convert.bodyToExpression') end, opts('Dart Convert To Expression'))
+vim.keymap.set('n', '<leader>pa', function() req.execute_code_action('refactor.convert.bodyToAsync') end, opts('Dart Convert To Async'))
+vim.keymap.set('n', '<leader>pb', function() req.execute_code_action('refactor.convert.bodyToBlock') end, opts('Dart Convert To Block'))
if vim.fn.getline(1):match('^#!.*dcli') then
vim.cmd [[comp dcli]]
else
vim.cmd [[comp dart]]
end
-
-require('lsp-format').disabled_filetypes.dart = true
diff --git a/lua/tms/first_load.lua b/lua/tms/first_load.lua
@@ -7,8 +7,6 @@ local install = function(repo, path) if vim.fn.isdirectory(path) == 0 then clone
local opt = function(repo) install(repo, string.format('%s/opt/%s', install_path, name(repo))) end
local start = function(repo) install(repo, string.format('%s/start/%s', install_path, name(repo))) end
-
opt('wbthomason/packer.nvim')
start('lewis6991/impatient.nvim')
start('tjdevries/colorbuddy.nvim')
-start('tjdevries/lsp-format.nvim')
diff --git a/lua/tms/ft/dart/lsp.lua b/lua/tms/ft/dart/lsp.lua
@@ -1,130 +0,0 @@
-local M = {}
-
-local get_visual = function()
- local curpos = vim.fn.getcurpos()
- local one = { row = curpos[2] - 1, col = curpos[3] - 1 }
- local two = { row = vim.fn.line('v') - 1, col = vim.fn.col('v') - 1 }
-
- if one.row == two.row then
- if one.col > two.col then
- local tmp = one
- one = two
- two = tmp
- end
- elseif one.row > two.row then
- local tmp = one
- one = two
- two = tmp
- end
-
- two.col = two.col + 1
-
- return { start = one, ['end'] = two }
-end
-
-local make_code_action_params = function()
- local params = vim.lsp.util.make_range_params()
- params.context = {
- diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
- }
- return params
-end
-
-local list_code_action_kinds = function()
- local params = make_code_action_params()
- local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params)
- for _, res in pairs(result or {}) do
- print('---', 'CODE ACTIONS')
- for _, r in pairs(res.result or {}) do
- -- vim.pretty_print(r)
- print(r.kind)
- end
- print('---')
- end
-end
-
-local execute_code_action = function(kind)
- if not kind then return end
- local params = make_code_action_params()
- params.context.only = { kind }
- local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params)
- for _, res in pairs(result or {}) do
- for _, r in pairs(res.result or {}) do
- if r.edit then
- vim.lsp.util.apply_workspace_edit(r.edit, 'utf-8')
- else
- vim.lsp.buf.execute_command(r.command)
- end
- end
- end
-end
-
--- TODO(tms) 22.04.22: possible bug that does not count new lines
-local get_offest_length = function(buf, mode)
- local vs = get_visual()
- D(mode, vs)
-
- local start_row_offset = vim.api.nvim_buf_get_offset(buf, vs.start.row)
- local start_col_offset = vim.lsp.util.character_offset(buf, vs.start.row, vs.start.col, 'utf-8')
- local start_offset = start_row_offset + start_col_offset
-
- if mode == 'v' then
- local end_row_offset = vim.api.nvim_buf_get_offset(buf, vs['end'].row)
- local end_col_offset = vim.lsp.util.character_offset(buf, vs['end'].row, vs['end'].col, 'utf-8')
- local end_offset = end_row_offset + end_col_offset
- local visual_length = end_offset - start_offset
- return start_offset, visual_length, end_offset
- elseif mode == 'V' then
- -- move offset to next line to count this one
- local end_row_offset = vim.api.nvim_buf_get_offset(buf, vs['end'].row + 1)
- local visual_length = end_row_offset - start_row_offset
- return start_row_offset, visual_length, end_row_offset
- else
- return start_offset, 0
- end
-end
-
-local make_params = function(buf, mode, command)
- local buf_name = vim.api.nvim_buf_get_name(buf)
- local offset, length = get_offest_length(buf, mode)
- return { command, buf_name, nil, offset, length }
-end
-
-local execute_simple_command = function(command)
- local cur_buf = vim.api.nvim_get_current_buf()
- local cur_buf_name = vim.api.nvim_buf_get_name(cur_buf)
- local params = { command = command, arguments = { cur_buf_name }, title = '' }
- vim.lsp.buf_request_sync(cur_buf, 'workspace/executeCommand', params)
-end
-
-local execute_command = function(command)
- local mode = vim.api.nvim_get_mode().mode
- local buf = vim.api.nvim_get_current_buf()
- local params = make_params(buf, mode, command)
- D(params)
- vim.ui.input({}, function(input)
- if input and #input ~= 0 then
- table.insert(params, { name = input })
- vim.lsp.buf_request(buf, 'workspace/executeCommand', { command = 'refactor.perform', arguments = params })
- end
- end)
-end
-
-local execute_command_no_input = function(command)
- local mode = vim.api.nvim_get_mode().mode
- local buf = vim.api.nvim_get_current_buf()
- local params = make_params(buf, mode, command)
- table.insert(params, { name = '' })
- D(params)
- vim.lsp.buf_request(buf, 'workspace/executeCommand', { command = 'refactor.perform', arguments = params })
-end
-
-M.organize_imports = function() execute_simple_command('edit.organizeImports') end
-M.fix_all = function() execute_simple_command('edit.fixAll') end
-M.extract_method = function() execute_command('EXTRACT_METHOD') end
-M.extract_local_variable = function() execute_command('EXTRACT_LOCAL_VARIABLE') end
-M.inline_local_variable = function() execute_command_no_input('INLINE_LOCAL_VARIABLE') end
-M.list_code_action_kinds = list_code_action_kinds
-M.execute_code_action = function(kind) execute_code_action(kind) end
-
-return M
diff --git a/lua/tms/lsp/init.lua b/lua/tms/lsp/init.lua
@@ -1,5 +1,13 @@
local servers = require('tms.lsp.servers')
-local format = require('lsp-format')
+
+local format_setup = function(client, bufnr)
+ vim.keymap.set('n', 'Q', function()
+ local params = vim.lsp.util.make_formatting_params({})
+ client.request('textDocument/formatting', params, nil, bufnr)
+ end, { buffer = bufnr, desc = 'LSP Format' })
+ vim.keymap
+ .set('v', 'Q', ':<c-u>lua vim.lsp.buf.range_formatting()<cr>', { buffer = bufnr, desc = 'LSP Range Format' })
+end
local on_attach = function(client, bufnr)
local lsp = vim.lsp
@@ -22,10 +30,7 @@ local on_attach = function(client, bufnr)
vim.keymap.set('v', 'ga', vim.lsp.buf.range_code_action, opts('LSP Code Actions'))
vim.keymap.set('n', 'gn', vim.lsp.buf.rename, opts('LSP Rename'))
- vim.keymap.set('n', 'Q', vim.lsp.buf.formatting, opts('LSP Format'))
- vim.keymap.set('v', 'Q', ':<c-u>lua vim.lsp.buf.range_formatting()<cr>', opts('LSP Range Format'))
-
- format.on_attach(client)
+ if not servers.no_format[client.name] then format_setup(client, bufnr) end
local has_aerial, aerial = pcall(require, 'aerial')
if has_aerial then aerial.on_attach(client, bufnr) end
@@ -40,32 +45,23 @@ local capabilities = function()
end
end
-local make_opts = function(name, server)
+local make_opts = function(name)
local opts = {}
opts.on_attach = on_attach
opts.capabilities = capabilities()
- opts = servers.setup(name, opts, server)
+ opts = servers.setup(name, opts)
return opts
end
local setup = function()
-
- format.setup()
-
-- LSP Installer
local has_lspi, lsp_installer = pcall(require, 'nvim-lsp-installer')
- if has_lspi then
- lsp_installer.on_server_ready(function(server)
- local opts = make_opts(server.name, server)
- server:setup(opts)
- end)
- end
+ if has_lspi then lsp_installer.setup({}) end
-- LSP Config
local has_lspc, lsp_config = pcall(require, 'lspconfig')
if has_lspc then
- local manual_servers = { 'gdscript', 'dartls' }
- for _, name in ipairs(manual_servers) do
+ for _, name in ipairs(servers.installed) do
local opts = make_opts(name)
lsp_config[name].setup(opts)
end
diff --git a/lua/tms/lsp/servers.lua b/lua/tms/lsp/servers.lua
@@ -1,75 +1,75 @@
-- Custom configuration for servers
local M = {}
+local S = {}
-M.setup = function(name, opts, server)
- local fn = M[name]
- if fn then opts = fn(opts, server) end
+M.installed = {
+ 'bashls',
+ 'clangd',
+ 'cmake',
+ 'cssls',
+ 'dockerls',
+ 'emmet_ls',
+ 'gopls',
+ 'html',
+ 'intelephense',
+ 'jdtls',
+ 'jsonls',
+ 'pyright',
+ 'rust_analyzer',
+ 'sumneko_lua',
+ 'tsserver',
+ 'vimls',
+ 'yamlls',
+ 'zls',
+}
+
+M.no_format = { sumneko_lua = true }
+
+M.setup = function(name, opts)
+ local fn = S[name]
+ if fn then opts = fn(opts) end
return opts
end
-M.jsonls = function(opts)
+S.jsonls = function(opts)
opts.settings = { json = { schemas = require('schemastore').json.schemas() } }
return opts
end
-M.yamlls = function(opts)
+S.yamlls = function(opts)
opts.settings = { yaml = { schemaStore = { enable = true } } }
return opts
end
-M.cssls = function(opts)
+S.cssls = function(opts)
opts.capabilities.textDocument.completion.completionItem.snippetSupport = true
return opts
end
-M.sumneko_lua = function(opts, server)
+S.sumneko_lua = function(opts)
opts.settings = {
- Lua = {
- runtime = { version = 'LuaJIT' },
- diagnostics = { globals = { 'vim' } },
- telemetry = { enable = false },
- -- format = {
- -- enable = true,
- -- defaultConfig = {
- -- indent_style = 'space',
- -- indent_size = '2',
- -- quote_style = 'single',
- -- call_arg_parentheses = 'keep',
- -- continuation_indent_size = '4',
- -- local_assign_continuation_align_to_first_expression = true,
- -- align_call_args = true,
- -- align_function_define_params = true,
- -- keep_one_space_between_table_and_bracket = true,
- -- align_table_field_to_first_field = true,
- -- continuous_assign_statement_align_to_equal_sign = true,
- -- continuous_assign_table_field_align_to_equal_sign = true,
- -- if_condition_no_continuation_indent = false,
- -- end_of_line = 'lf',
- -- },
- -- },
- },
+ Lua = { runtime = { version = 'LuaJIT' }, diagnostics = { globals = { 'vim' } }, telemetry = { enable = false } },
}
- opts = vim.tbl_deep_extend('force', server:get_default_options(), opts)
- opts = require('lua-dev').setup({ lspconfig = opts })
+ -- opts = require('lua-dev').setup({ lspconfig = opts })
return opts
end
-M.emmet_ls = function(opts)
+S.emmet_ls = function(opts)
opts.root_dir = require('lspconfig').util.root_pattern('.git', vim.fn.getcwd())
return opts
end
-M.gopls = function(opts)
+S.gopls = function(opts)
opts.root_dir = require('lspconfig').util.root_pattern('go.work', 'go.mod', '.git', vim.fn.getcwd())
return opts
end
-M.html = function(opts)
+S.html = function(opts)
opts.init_options = { provideFormatter = false }
return opts
end
-M.dartls = function(opts)
+S.dartls = function(opts)
opts.cmd = require('tms.ft.dart.bin').lsp_cmd()
opts.init_options = { closingLabels = true, outline = true }
-- filetypes = {'dart', 'html'}
@@ -79,7 +79,7 @@ M.dartls = function(opts)
return opts
end
-M.intelephense = function(opts)
+S.intelephense = function(opts)
opts.init_options = {
clearCache = true,
licenceKey = os.getenv('XDG_CONFIG_HOME') .. '/intelephense/licenceKey.txt',
diff --git a/lua/tms/plugins.lua b/lua/tms/plugins.lua
@@ -42,6 +42,10 @@ return packer.startup({
use 'windwp/nvim-spectre'
use { 'sidebar-nvim/sidebar.nvim', requires = { 'kyazdani42/nvim-web-devicons' } }
+ -- lua
+ use 'nanotee/luv-vimdocs'
+ use 'milisims/nvim-luaref'
+
-- Notes
use { 'nvim-neorg/neorg', requires = { 'nvim-lua/plenary.nvim' } }
use { 'mickael-menu/zk-nvim', requires = { 'neovim/nvim-lspconfig' } }
@@ -106,7 +110,6 @@ return packer.startup({
use 'folke/lua-dev.nvim'
use { 'jose-elias-alvarez/null-ls.nvim', requires = { 'nvim-lua/plenary.nvim' } }
use 'stevearc/aerial.nvim'
- use 'lukas-reineke/lsp-format.nvim'
-- dap
use 'mfussenegger/nvim-dap'
@@ -135,6 +138,7 @@ return packer.startup({
-- personal
use 'GenesisTMS/trans.nvim'
+ use '~/dev/nvim/plugins/dartls-helper'
-- database
use 'tpope/vim-dadbod'
diff --git a/test/dart.dart b/test/dart.dart
@@ -9,3 +9,4 @@ class Test {
}
var a = Test();
+