Skip to content

Commit

Permalink
Merge pull request #3397 from bhcleek/syntax/generics
Browse files Browse the repository at this point in the history
syntax: add support for generics
  • Loading branch information
bhcleek authored Apr 13, 2022
2 parents 0b713cf + 6aeeba2 commit 080e44d
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 6 deletions.
110 changes: 110 additions & 0 deletions autoload/go/highlight_test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,12 @@ function! Test_goReceiverHighlight() abort
\ 'ValueReceiverType': {'group': 'goReceiverType', 'value': "t T\x1f"},
\ 'PointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "*T\x1f"},
\ 'ValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "T\x1f"},
\ 'GenericPointerReceiverVar': {'group': 'goReceiverVar', 'value': "g\x1f *G[int]"},
\ 'GenericValueReceiverVar': {'group': 'goReceiverVar', 'value': "g\x1f G[int]"},
\ 'GenericPointerReceiverType': {'group': 'goReceiverType', 'value': "g *G\x1f[int]"},
\ 'GenericValueReceiverType': {'group': 'goReceiverType', 'value': "g G\x1f[int]"},
\ 'GenericPointerReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "*G\x1f[int]"},
\ 'GenericValueReceiverTypeOmittedVar': {'group': 'goReceiverType', 'value': "G\x1f[int]"},
\ }

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

Expand All @@ -505,6 +512,109 @@ function! s:receiverHighlightGroup(testname, value)
endtry
endfunc

function! Test_GoTypeHighlight() abort
syntax on

let l:tests = {
\ 'StandardType': {'group': 'goTypeName', 'value': "T\x1f"},
\ 'GenericType': {'group': 'goTypeName', 'value': "G\x1f[T any]"},
\ }

let g:go_highlight_types = 1
for l:kv in items(l:tests)
let l:actual = s:typeHighlightGroup(l:kv[0], l:kv[1].value)
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
endfor
unlet g:go_highlight_types
endfunc

function! s:typeHighlightGroup(testname, value)
let l:package = tolower(a:testname)
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
\ printf('package %s', l:package),
\ '',
\ printf('type %s struct{}', a:value),
\ ])

try
let l:pos = getcurpos()
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
return l:actual
finally
call delete(l:dir, 'rf')
endtry
endfunc

function! Test_goFunction() abort
syntax on

let l:tests = {
\ 'StandardFunction': {'group': 'goFunction', 'value': "F\x1f(){}"},
\ 'GenericFunction': {'group': 'goFunction', 'value': "G\x1f[T any](_ T){}"},
\ }

let g:go_highlight_functions = 1
for l:kv in items(l:tests)
let l:actual = s:functionHighlightGroup(l:kv[0], l:kv[1].value)
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
endfor
unlet g:go_highlight_functions
endfunc

function! s:functionHighlightGroup(testname, value)
let l:package = tolower(a:testname)
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
\ printf('package %s', l:package),
\ '',
\ printf('func %s', a:value),
\ ])

try
let l:pos = getcurpos()
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
return l:actual
finally
call delete(l:dir, 'rf')
endtry
endfunc

function! Test_goFunctionCall() abort
syntax on

let l:tests = {
\ 'StandardFunctionCall': {'group': 'goFunctionCall', 'value': "f\x1f()"},
\ 'GenericFunctionCall': {'group': 'goFunctionCall', 'value': "g\x1f[int](i)"},
\ }

let g:go_highlight_function_calls = 1
for l:kv in items(l:tests)
let l:actual = s:functionCallHighlightGroup(l:kv[0], l:kv[1].value)
call assert_equal(l:kv[1].group, l:actual, l:kv[0])
endfor
unlet g:go_highlight_function_calls
endfunc

function! s:functionCallHighlightGroup(testname, value)
let l:package = tolower(a:testname)
let l:dir = gotest#write_file(printf('%s/%s.go', l:package, a:testname), [
\ printf('package %s', l:package),
\ '',
\ 'func f() {}',
\ 'func g[T any](i T) {}',
\ 'func init() {',
\ printf("\t%s", a:value),
\ '}',
\ ])

try
let l:pos = getcurpos()
let l:actual = synIDattr(synID(l:pos[1], l:pos[2], 1), 'name')
return l:actual
finally
call delete(l:dir, 'rf')
endtry
endfunc

" restore Vi compatibility settings
let &cpo = s:cpo_save
unlet s:cpo_save
Expand Down
37 changes: 31 additions & 6 deletions syntax/go.vim
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,46 @@ if go#config#HighlightOperators()
syn match goOperator /\%(<<\|>>\|&^\)=\?/
" match remaining two-char operators: := && || <- ++ --
syn match goOperator /:=\|||\|<-\|++\|--/
" match ~
syn match goOperator /\~/
" match ...

hi def link goPointerOperator goOperator
hi def link goVarArgs goOperator
endif
hi def link goOperator Operator

" -> type constraint opening bracket
" |-> start non-counting group
" || -> any word character
" || | -> at least one, as many as possible
" || | | -> start non-counting group
" || | | | -> match ~
" || | | | | -> at most once
" || | | | | | -> allow a slice type
" || | | | | | | -> any word character
" || | | | | | | | -> start a non-counting group
" || | | | | | | | | -> that matches word characters and |
" || | | | | | | | | | -> close the non-counting group
" || | | | | | | | | | | -> close the non-counting group
" || | | | | | | | | | | |-> any number of matches
" || | | | | | | | | | | || -> start a non-counting group
" || | | | | | | | | | | || | -> a comma and whitespace
" || | | | | | | | | | | || | | -> at most once
" || | | | | | | | | | | || | | | -> close the non-counting group
" || | | | | | | | | | | || | | | | -> at least one of those non-counting groups, as many as possible
" || | | | | | -------- | | | | || | | | | | -> type constraint closing bracket
" || | | | | || | | | | | || | | | | | |
syn match goTypeParams /\[\%(\w\+\s\+\%(\~\?\%(\[]\)\?\w\%(\w\||\)\)*\%(,\s*\)\?\)\+\]/ nextgroup=goSimpleParams,goDeclType contained

" Functions;
if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters()
syn match goDeclaration /\<func\>/ nextgroup=goReceiver,goFunction,goSimpleParams skipwhite skipnl
syn match goReceiverDecl /(\s*\zs\%(\%(\w\+\s\+\)\?\*\?\w\+\)\ze\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator
syn match goReceiverDecl /(\s*\zs\%(\%(\w\+\s\+\)\?\*\?\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\)\ze\s*)/ contained contains=goReceiverVar,goReceiverType,goPointerOperator
syn match goReceiverVar /\w\+\ze\s\+\%(\w\|\*\)/ nextgroup=goPointerOperator,goReceiverType skipwhite skipnl contained
syn match goPointerOperator /\*/ nextgroup=goReceiverType contained skipwhite skipnl
syn match goFunction /\w\+/ nextgroup=goSimpleParams contained skipwhite skipnl
syn match goReceiverType /\w\+\ze\s*)/ contained
syn match goFunction /\w\+/ nextgroup=goSimpleParams,goTypeParams contained skipwhite skipnl
syn match goReceiverType /\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\ze\s*)/ contained
if go#config#HighlightFunctionParameters()
syn match goSimpleParams /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType nextgroup=goFunctionReturn skipwhite skipnl
syn match goFunctionReturn /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/ contained contains=goParamName,goType skipwhite skipnl
Expand All @@ -290,15 +315,15 @@ if go#config#HighlightFunctions() || go#config#HighlightFunctionParameters()
hi def link goReceiverVar goParamName
hi def link goParamName Identifier
endif
syn match goReceiver /(\s*\%(\w\+\s\+\)\?\*\?\s*\w\+\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl
syn match goReceiver /(\s*\%(\w\+\s\+\)\?\*\?\s*\w\+\%(\[\%(\%(\[\]\)\?\w\+\%(,\s*\)\?\)\+\]\)\?\s*)\ze\s*\w/ contained nextgroup=goFunction contains=goReceiverDecl skipwhite skipnl
else
syn keyword goDeclaration func
endif
hi def link goFunction Function

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

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

0 comments on commit 080e44d

Please sign in to comment.