Skip to content

Commit

Permalink
syntax: don't pick up chan chains (channel of channels)
Browse files Browse the repository at this point in the history
This is a very weird error. We want to show an error if the chan
statement is in form of:

	<- chan
	chan <-

The correct form should be of course:

	<-chan
	chan<-

But for example, if we have a channel of channels (like below), the
selected piece of whitespace is also highlighted as an error

	chan<- chan<-
	      ^

Because it's the part of `<- chan`, whereas we should not treat as an
error because we have two `chan<-` and `chan<-` statements.

To fix this, we add a `negative lookbehind` regex statement. It will not
match a text if it's preceded with other text.

First let assemble the current regex for the case: `<- chan`
(receive-only annotation), which is:

	\(<-\)\@<=\s\+\(chan\>\)\@=

The first part is:

	\(<-\)\@<=\s\+\

Here the pattern \@<= matches with zero width if the preceding atom
matches just before what follows. `\s\+` means white space of at least
one character. So it matches **whitespaces** which precedes the
statement `<-`

Now the second part is only useful with the first part. I've added the
placeholder to make it more readable:

	PLACEHOLDER(chan\>\)\@="

First the pattern `\@=` means to match the preceding atom with zero
width. So it will match the **PLACEHOLDER** till it finds a `chan`
statement. Once it finds it, it doesn't proceed anymore. So we only
highlight the whitespaces between `<-` and `chan` only if we have a
white space of at least one character

Finally we can introduce our fix now. We're going to pick the `<-`
statemetn if it doesn't follow a `chan`. So `chan<-` should NOT trigger
an error anymore, because we're not going to pick arrows in that form.

To match an arrow which doesn't follow a chan statement can be done via
a `negative lookbehind`, which is in the form of:

	\(chan\)\@<!<-

This literally means: "Match `<-` only if it doesn't follow `chan`.
We're going to use this pattern for the plain `<-` pattern. Not we're
just going to replace this into our current regex:

This original regex:

	\(<-\)\@<=\s\+\(chan\>\)\@=

will be changed into:

	\(\(chan\)\@<!<-\)\@<=\s\+\(chan\>\)\@=

Fixes #655
  • Loading branch information
fatih committed Jan 3, 2016
1 parent 70c3630 commit 19972de
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions syntax/go.vim
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,19 @@ endif
" Spacing errors around the 'chan' keyword
if g:go_highlight_chan_whitespace_error != 0
" receive-only annotation on chan type
syn match goSpaceError display "\(<-\)\@<=\s\+\(chan\>\)\@="
"
" \(\<chan\>\)\@<!<- (only pick arrow when it doesn't come after a chan)
" this prevents picking up 'chan<- chan<-' but not '<- chan'
syn match goSpaceError display "\(\(\<chan\>\)\@<!<-\)\@<=\s\+\(\<chan\>\)\@="

" send-only annotation on chan type
syn match goSpaceError display "\(\<chan\)\@<=\s\+\(<-\)\@="
"
" \(<-\)\@<!\<chan\> (only pick chan when it doesn't come after an arrow)
" this prevents picking up '<-chan <-chan' but not 'chan <-'
syn match goSpaceError display "\(\(<-\)\@<!\<chan\>\)\@<=\s\+\(<-\)\@="

" value-ignoring receives in a few contexts
syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+"
syn match goSpaceError display "\(\(^\|[={(,;]\)\s*<-\)\@<=\s\+f"
endif

" Extra types commonly seen
Expand Down

0 comments on commit 19972de

Please sign in to comment.