Skip to content

Commit 080e44d

Browse files
authored
Merge pull request #3397 from bhcleek/syntax/generics
syntax: add support for generics
2 parents 0b713cf + 6aeeba2 commit 080e44d

File tree

2 files changed

+141
-6
lines changed

2 files changed

+141
-6
lines changed

autoload/go/highlight_test.vim

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,12 @@ function! Test_goReceiverHighlight() abort
477477
\ 'ValueReceiverType': {'group': 'goReceiverType', 'value': "t T\x1f"},
478478
\ 'PointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "*T\x1f"},
479479
\ 'ValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "T\x1f"},
480+
\ 'GenericPointerReceiverVar': {'group': 'goReceiverVar', 'value': "g\x1f *G[int]"},
481+
\ 'GenericValueReceiverVar': {'group': 'goReceiverVar', 'value': "g\x1f G[int]"},
482+
\ 'GenericPointerReceiverType': {'group': 'goReceiverType', 'value': "g *G\x1f[int]"},
483+
\ 'GenericValueReceiverType': {'group': 'goReceiverType', 'value': "g G\x1f[int]"},
484+
\ 'GenericPointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "*G\x1f[int]"},
485+
\ 'GenericValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "G\x1f[int]"},
480486
\ }
481487

482488
let g:go_highlight_function_parameters = 1
@@ -493,6 +499,7 @@ function! s:receiverHighlightGroup(testname, value)
493499
\ printf('package %s', l:package),
494500
\ '',
495501
\ 'type T struct{}',
502+
\ 'type G[T any] struct{}',
496503
\ printf('func (%s) Foo() {}', a:value),
497504
\ ])
498505

@@ -505,6 +512,109 @@ function! s:receiverHighlightGroup(testname, value)
505512
endtry
506513
endfunc
507514

515+
function! Test_GoTypeHighlight() abort
516+
syntax on
517+
518+
let l:tests = {
519+
\ 'StandardType': {'group': 'goTypeName', 'value': "T\x1f"},
520+
\ 'GenericType': {'group': 'goTypeName', 'value': "G\x1f[T any]"},
521+
\ }
522+
523+
let g:go_highlight_types = 1
524+
for l:kv in items(l:tests)
525+
let l:actual = s:typeHighlightGroup(l:kv[0], l:kv[1].value)
526+
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
527+
endfor
528+
unlet g:go_highlight_types
529+
endfunc
530+
531+
function! s:typeHighlightGroup(testname, value)
532+
let l:package = tolower(a:testname)
533+
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
534+
\ printf('package %s', l:package),
535+
\ '',
536+
\ printf('type %s struct{}', a:value),
537+
\ ])
538+
539+
try
540+
let l:pos = getcurpos()
541+
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
542+
return l:actual
543+
finally
544+
call delete(l:dir, 'rf')
545+
endtry
546+
endfunc
547+
548+
function! Test_goFunction() abort
549+
syntax on
550+
551+
let l:tests = {
552+
\ 'StandardFunction': {'group': 'goFunction', 'value': "F\x1f(){}"},
553+
\ 'GenericFunction': {'group': 'goFunction', 'value': "G\x1f[T any](_ T){}"},
554+
\ }
555+
556+
let g:go_highlight_functions = 1
557+
for l:kv in items(l:tests)
558+
let l:actual = s:functionHighlightGroup(l:kv[0], l:kv[1].value)
559+
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
560+
endfor
561+
unlet g:go_highlight_functions
562+
endfunc
563+
564+
function! s:functionHighlightGroup(testname, value)
565+
let l:package = tolower(a:testname)
566+
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
567+
\ printf('package %s', l:package),
568+
\ '',
569+
\ printf('func %s', a:value),
570+
\ ])
571+
572+
try
573+
let l:pos = getcurpos()
574+
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
575+
return l:actual
576+
finally
577+
call delete(l:dir, 'rf')
578+
endtry
579+
endfunc
580+
581+
function! Test_goFunctionCall() abort
582+
syntax on
583+
584+
let l:tests = {
585+
\ 'StandardFunctionCall': {'group': 'goFunctionCall', 'value': "f\x1f()"},
586+
\ 'GenericFunctionCall': {'group': 'goFunctionCall', 'value': "g\x1f[int](i)"},
587+
\ }
588+
589+
let g:go_highlight_function_calls = 1
590+
for l:kv in items(l:tests)
591+
let l:actual = s:functionCallHighlightGroup(l:kv[0], l:kv[1].value)
592+
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
593+
endfor
594+
unlet g:go_highlight_function_calls
595+
endfunc
596+
597+
function! s:functionCallHighlightGroup(testname, value)
598+
let l:package = tolower(a:testname)
599+
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
600+
\ printf('package %s', l:package),
601+
\ '',
602+
\ 'func f() {}',
603+
\ 'func g[T any](i T) {}',
604+
\ 'func init() {',
605+
\ printf("\t%s", a:value),
606+
\ '}',
607+
\ ])
608+
609+
try
610+
let l:pos = getcurpos()
611+
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
612+
return l:actual
613+
finally
614+
call delete(l:dir, 'rf')
615+
endtry
616+
endfunc
617+
508618
" restore Vi compatibility settings
509619
let &cpo = s:cpo_save
510620
unlet s:cpo_save

syntax/go.vim

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,21 +266,46 @@ if go#config#HighlightOperators()
266266
syn match goOperator /\%(<<\|>>\|&^\)=\?/
267267
" match remaining two-char operators: := && || <- ++ --
268268
syn match goOperator /:=\|||\|<-\|++\|--/
269+
" match ~
270+
syn match goOperator /\~/
269271
" match ...
270272

271273
hi def link goPointerOperator goOperator
272274
hi def link goVarArgs goOperator
273275
endif
274276
hi def link goOperator Operator
275277

278+
" -> type constraint opening bracket
279+
" |-> start non-counting group
280+
" || -> any word character
281+
" || | -> at least one, as many as possible
282+
" || | | -> start non-counting group
283+
" || | | | -> match ~
284+
" || | | | | -> at most once
285+
" || | | | | | -> allow a slice type
286+
" || | | | | | | -> any word character
287+
" || | | | | | | | -> start a non-counting group
288+
" || | | | | | | | | -> that matches word characters and |
289+
" || | | | | | | | | | -> close the non-counting group
290+
" || | | | | | | | | | | -> close the non-counting group
291+
" || | | | | | | | | | | |-> any number of matches
292+
" || | | | | | | | | | | || -> start a non-counting group
293+
" || | | | | | | | | | | || | -> a comma and whitespace
294+
" || | | | | | | | | | | || | | -> at most once
295+
" || | | | | | | | | | | || | | | -> close the non-counting group
296+
" || | | | | | | | | | | || | | | | -> at least one of those non-counting groups, as many as possible
297+
" || | | | | | -------- | | | | || | | | | | -> type constraint closing bracket
298+
" || | | | | || | | | | | || | | | | | |
299+
syn match goTypeParams /\[\%(\w\+\s\+\%(\~\?\%(\[]\)\?\w\%(\w\||\)\)*\%(,\s*\)\?\)\+\]/ nextgroup=goSimpleParams,goDeclType contained
300+
276301
" Functions;
277302
if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters()
278303
syn match goDeclaration /\<func\>/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl
279-
syn match goReceiverDecl /(\s*\zs\%(\%(\w\+\s\+\)\?\*\?\w\+\)\ze\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator
304+
syn match goReceiverDecl /(\s*\zs\%(\%(\w\+\s\+\)\?\*\?\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\)\ze\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator
280305
syn match goReceiverVar /\w\+\ze\s\+\%(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained
281306
syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl
282-
syn match goFunction /\w\+/ nextgroup=goSimpleParams contained skipwhite skipnl
283-
syn match goReceiverType /\w\+\ze\s*)/ contained
307+
syn match goFunction /\w\+/ nextgroup=goSimpleParams,goTypeParams contained skipwhite skipnl
308+
syn match goReceiverType /\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\ze\s*)/ contained
284309
if go#config#HighlightFunctionParameters()
285310
syn match goSimpleParams /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl
286311
syn match goFunctionReturn /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl
@@ -290,15 +315,15 @@ if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters()
290315
hi def link goReceiverVar goParamName
291316
hi def link goParamName Identifier
292317
endif
293-
syn match goReceiver /(\s*\%(\w\+\s\+\)\?\*\?\s*\w\+\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl
318+
syn match goReceiver /(\s*\%(\w\+\s\+\)\?\*\?\s*\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl
294319
else
295320
syn keyword goDeclaration func
296321
endif
297322
hi def link goFunction Function
298323

299324
" Function calls;
300325
if go#config#HighlightFunctionCalls()
301-
syn match goFunctionCall /\w\+\ze(/ contains=goBuiltins,goDeclaration
326+
syn match goFunctionCall /\w\+\ze\%(\[\%(\%(\[]\)\?\w\+\(,\s*\)\?\)\+\]\)\?(/ contains=goBuiltins,goDeclaration
302327
endif
303328
hi def link goFunctionCall Type
304329

@@ -325,7 +350,7 @@ hi def link goField Identifier
325350
if go#config#HighlightTypes()
326351
syn match goTypeConstructor /\<\w\+{\@=/
327352
syn match goTypeDecl /\<type\>/ nextgroup=goTypeName skipwhite skipnl
328-
syn match goTypeName /\w\+/ contained nextgroup=goDeclType skipwhite skipnl
353+
syn match goTypeName /\w\+/ contained nextgroup=goDeclType,goTypeParams skipwhite skipnl
329354
syn match goDeclType /\<\%(interface\|struct\)\>/ skipwhite skipnl
330355
hi def link goReceiverType Type
331356
else

0 commit comments

Comments
 (0)