Skip to content

Commit a164cb4

Browse files
authored
Merge pull request #71 from heavenshell/fix/multiline_function
Fix/multiline function
2 parents 8b37e9c + 2773975 commit a164cb4

File tree

8 files changed

+622
-49
lines changed

8 files changed

+622
-49
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
.swp
1+
*.swp
22
*~
33
.DS_Store
44
tags
5+
tests/vader.vim

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
sudo: required
22
dist: xenial
33
language: vim
4-
node_js: stable
54

65
install:
76
- git clone https://github.com/junegunn/vader.vim.git tests/vader.vim
87
- git clone https://github.com/vim/vim /tmp/vim
9-
- mkdir ~/bin
108
- cd /tmp/vim
119
- sudo apt-get install -y gettext libncurses5-dev libacl1-dev libgpm-dev
1210
- ./configure --with-features=huge --enable-fail-if-missing --enable-pythoninterp --prefix=$HOME/bin/vim

autoload/jsdoc.vim

Lines changed: 60 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ endif
100100
" Currently `(` and `)` are deleted by substitute().
101101
" @see jsdoc#insert() for where these regexes are matched to the string
102102
let s:regexs = {
103-
\ 'function_declaration': '^.\{-}\s*function\s*\*\?\s\+\([a-zA-Z_$][a-zA-Z0-9_$]*\)\s*\**(\s*\([^)]*\)\s*).*$',
103+
\ 'function_declaration': '^.\{-}\s*function\s*\*\?\s\+\([a-zA-Z_$][a-zA-Z0-9_$]*\)\s*(\s*\([^)]*\)\s*).*$',
104104
\ 'function_expression': '^.\{-}\s*\([a-zA-Z_$][a-zA-Z0-9_$]*\)\s*[:=]\s*function\s*\**\s*(\s*\([^)]*\)\s*).*$',
105105
\ 'anonymous_function': '^.\{-}\s*function\s*\**\s*(\s*\([^)]*\)\s*).*$',
106106
\ 'class_extend': '^.\{-}\s*class\s*\([a-zA-Z_$][a-zA-Z0-9_$]*\)*\s*extends\s*\(\([^{]*\)\).*$',
@@ -111,9 +111,10 @@ let s:regexs = {
111111
\ 'arrow_single': '^.\{-}\s*\([a-zA-Z_$][a-zA-Z0-9_$]*\)\s*[:=]\s*\([^=]*\).*$',
112112
\ 'return_type': ')\(:\|:\s\|\s*:\s*\)\([a-zA-Z]\+\).*$',
113113
\ 'interface': '^.\{-}\s*interface\s*\([a-zA-Z_$][a-zA-Z0-9_$]*\).*$',
114+
\ 'flow_type': '^.\{-}\s*type\s*\([a-zA-Z_$][a-zA-Z0-9_$]*\).*$',
114115
\ 'access': '^\s*\(public\|protected\|private\)',
115116
\ 'implements': '^.\{-}\s*implements\s*\(\([^{]*\)\).*$',
116-
\ 'extends': '^.\{-}\s*extends\s*\([^\s*]\)'
117+
\ 'extends': '^.\{-}\s*extends\s*\([^\s*]\)',
117118
\ }
118119

119120
function! s:trim(value)
@@ -181,7 +182,12 @@ endfunction
181182
function! s:hookArgs(lines, space, arg, hook, argType, argDescription) abort
182183
" Hook function signature's args for insert as default value.
183184
if g:jsdoc_custom_args_hook == {}
184-
call add(a:lines, a:space . ' * @' . g:jsdoc_tags['param'] . ' ' . a:arg)
185+
if a:argType == ''
186+
let param = printf(' * @%s %s', g:jsdoc_tags['param'], a:arg)
187+
else
188+
let param = printf(' * @%s {%s} %s', g:jsdoc_tags['param'], a:argType, a:arg)
189+
endif
190+
call add(a:lines, a:space . param)
185191
else
186192

187193
let l:matchedArg = ''
@@ -245,44 +251,49 @@ function! s:determine_style(line)
245251
let l:is_named = 0
246252
let l:is_static = 0
247253
let l:is_interface = 0
254+
let l:is_type = 0
248255
let l:regex = 0
249256

250257
if a:line =~ s:regexs['function_declaration']
251-
let l:is_function = 1
252-
let l:is_named = 1
253-
let l:regex = s:regexs['function_declaration']
258+
let l:is_function = 1
259+
let l:is_named = 1
260+
let l:regex = s:regexs['function_declaration']
254261
elseif a:line =~ s:regexs['function_expression']
255-
let l:is_function = 1
256-
let l:is_named = 1
257-
let l:regex = s:regexs['function_expression']
262+
let l:is_function = 1
263+
let l:is_named = 1
264+
let l:regex = s:regexs['function_expression']
258265
elseif a:line =~ s:regexs['anonymous_function']
259-
let l:is_function = 1
260-
let l:regex = s:regexs['anonymous_function']
266+
let l:is_function = 1
267+
let l:regex = s:regexs['anonymous_function']
261268
elseif g:jsdoc_enable_es6 == 1 && a:line =~ s:regexs['static']
262-
let l:is_function = 1
263-
let l:is_named = 1
264-
let l:is_static = 1
265-
let l:regex = s:regexs['static']
269+
let l:is_function = 1
270+
let l:is_named = 1
271+
let l:is_static = 1
272+
let l:regex = s:regexs['static']
266273
elseif (g:jsdoc_allow_shorthand == 1 || g:jsdoc_enable_es6 == 1) && a:line =~ s:regexs['shorthand']
267-
let l:is_function = 1
268-
let l:is_named = 1
269-
let l:regex = s:regexs['shorthand']
274+
let l:is_function = 1
275+
let l:is_named = 1
276+
let l:regex = s:regexs['shorthand']
270277
elseif g:jsdoc_enable_es6 == 1 && a:line =~ s:regexs['arrow']
271-
let l:is_function = 1
272-
let l:is_named = 1
273-
let l:regex = s:regexs['arrow']
278+
let l:is_function = 1
279+
let l:is_named = 1
280+
let l:regex = s:regexs['arrow']
281+
elseif a:line =~ s:regexs['flow_type']
282+
let l:is_type = 1
283+
let l:is_named = 1
284+
let l:regex = s:regexs['flow_type']
274285
elseif g:jsdoc_enable_es6 == 1 && a:line =~ s:regexs['arrow_single']
275-
let l:is_function = 1
276-
let l:is_named = 1
277-
let l:regex = s:regexs['arrow_single']
286+
let l:is_function = 1
287+
let l:is_named = 1
288+
let l:regex = s:regexs['arrow_single']
278289
elseif g:jsdoc_enable_es6 == 1 && a:line =~ s:regexs['class_extend']
279-
let l:is_class = 1
280-
let l:is_named = 1
281-
let l:regex = s:regexs['class_extend']
290+
let l:is_class = 1
291+
let l:is_named = 1
292+
let l:regex = s:regexs['class_extend']
282293
elseif g:jsdoc_enable_es6 == 1 && a:line =~ s:regexs['class']
283-
let l:is_class = 1
284-
let l:is_named = 1
285-
let l:regex = s:regexs['class']
294+
let l:is_class = 1
295+
let l:is_named = 1
296+
let l:regex = s:regexs['class']
286297
elseif a:line =~ s:regexs['interface']
287298
let l:is_interface = 1
288299
let l:is_named = 1
@@ -295,6 +306,7 @@ function! s:determine_style(line)
295306
\ 'is_named': l:is_named,
296307
\ 'is_static': l:is_static,
297308
\ 'is_interface': l:is_interface,
309+
\ 'is_type': l:is_type,
298310
\ 'regex': l:regex,
299311
\ }
300312
endfunction
@@ -327,7 +339,16 @@ function! s:parse_keyword_arg(arg)
327339
endfunction
328340

329341
function! jsdoc#insert() abort
330-
let l:line = getline('.')
342+
let startpos = line('.')
343+
" Move cursor to the head.
344+
silent! execute 'normal! ^'
345+
if match(getline('.'), '\w$') != -1
346+
let l:line = getline('.')
347+
else
348+
let insertpos = search('{\|)\s*{\|){\|=>\s*{')
349+
let l:line = join(getline(startpos, insertpos))
350+
endif
351+
331352
let l:indentCharSpace = ' '
332353
let l:indentCharTab = ' '
333354
let l:autoexpandtab = &l:expandtab
@@ -338,44 +359,37 @@ function! jsdoc#insert() abort
338359
let l:indentChar = l:indentCharTab
339360
elseif l:autoexpandtab == 1 " expandtab
340361
" spaces
341-
let l:indent = indent('.')
362+
let l:indent = indent(startpos)
342363
let l:indentChar = l:indentCharSpace
343364
endif
344365

345366
let l:space = repeat(l:indentChar, l:indent)
346367

347-
" Determine function defintion style
368+
" Determine function definition style
348369
let l:style = s:determine_style(l:line)
349370
let l:is_class = l:style['is_class']
350371
let l:is_function = l:style['is_function']
351372
let l:is_named = l:style['is_named']
352373
let l:is_static = l:style['is_static']
353374
let l:is_interface = l:style['is_interface']
375+
let l:is_type = l:style['is_type']
354376
let l:regex = l:style['regex']
355377

356378
let l:lines = []
357379
let l:desc = g:jsdoc_input_description == 1 ? input('Description: ') : ''
358380
call add(l:lines, l:space . '/**')
359381
call add(l:lines, l:space . ' * ' . l:desc)
360382
" Class and interface generate only typed name.
361-
if !l:is_class && !l:is_interface
383+
if !l:is_class && !l:is_interface && !l:is_type
362384
call add(l:lines, l:space . ' *')
363385
endif
364386

365387
let l:funcName = ''
366388
let l:parent_class = ''
367389
let l:implements = ''
368390
let l:return_type = ''
369-
if l:is_function || l:is_class || l:is_interface
370-
391+
if l:is_function || l:is_class || l:is_interface || l:is_type
371392
" Parse function definition
372-
" @FIXME: Does not work if function is split over several lines...
373-
" e.g.
374-
" ```
375-
" function name(
376-
" arg1
377-
" arg2
378-
" ) { }
379393
let l:argString = ''
380394
if l:is_named
381395
let l:funcName = substitute(l:line, l:regex, '\1', 'g')
@@ -474,6 +488,7 @@ function! jsdoc#insert() abort
474488

475489
call add(l:lines, l:space . ' * @extends ' . '{' . l:parent_class . '}')
476490
endif
491+
elseif l:is_type
477492
elseif g:jsdoc_return == 1
478493
if g:jsdoc_allow_input_prompt == 1
479494
let s:candidate_type = l:return_type
@@ -502,9 +517,8 @@ function! jsdoc#insert() abort
502517
let l:paste = &g:paste
503518
let &g:paste = 1
504519

505-
call append(line('.') - 1, l:lines)
506-
507-
let l:pos = line('.') - (len(l:lines) - 1)
520+
call append(startpos - 1, l:lines)
521+
let l:pos = startpos + 1
508522

509523
silent! execute 'normal! ' . l:pos . 'G$'
510524
if l:desc ==# '' && l:funcName !=# ''

tests/flow.vader

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# vim:set et sw=4 ts=4 tw=79:
2+
Given javascript (typed):
3+
function foo(foo: string = 'foo', bar: number = 1): string {
4+
return 'foo'
5+
}
6+
7+
Execute:
8+
JsDoc
9+
10+
Expect javascript:
11+
/**
12+
* foo
13+
*
14+
* @param {string} foo='foo'
15+
* @param {number} bar=1
16+
* @returns {string}
17+
*/
18+
function foo(foo: string = 'foo', bar: number = 1): string {
19+
return 'foo'
20+
}
21+
22+
Given javascript (union):
23+
function foo(): number | string {
24+
return 'foo'
25+
}
26+
27+
Execute:
28+
JsDoc
29+
30+
Expect javascript:
31+
/**
32+
* foo
33+
*
34+
* @returns {number | string}
35+
*/
36+
function foo(): number | string {
37+
return 'foo'
38+
}
39+
40+
Given javascript (interface):
41+
type Props = {
42+
foo?: string
43+
}
44+
45+
Execute:
46+
JsDoc
47+
48+
Expect javascript:
49+
/**
50+
* Props
51+
*/
52+
type Props = {
53+
foo?: string
54+
}
55+
56+
Given javascript (implements):
57+
class Bar extends Foo implements IFoo {
58+
}
59+
60+
Execute:
61+
JsDoc
62+
63+
Expect javascript:
64+
/**
65+
* Bar
66+
*
67+
* @implements {IFoo}
68+
* @extends {Foo}
69+
*/
70+
class Bar extends Foo implements IFoo {
71+
}
72+
73+
Given javascript (scope arguments):
74+
class Bar extends Foo<Props> {
75+
constructor(arg1: string, arg2: string) {
76+
super()
77+
}
78+
}

0 commit comments

Comments
 (0)