diff --git a/Syntaxes/Ruby.plist b/Syntaxes/Ruby.plist
index 2802c0b..458f3a9 100644
--- a/Syntaxes/Ruby.plist
+++ b/Syntaxes/Ruby.plist
@@ -110,38 +110,655 @@
1
name
- keyword.control.class.ruby
+ punctuation.definition.constant.ruby
+
+
+ comment
+ symbols as hash key (1.9 syntax)
+ match
+ (?>[a-zA-Z_]\w*(?>[?!])?)(:)(?!:)
+ name
+ constant.other.symbol.hashkey.ruby
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.definition.constant.ruby
+
+
+ comment
+ symbols as hash key (1.8 syntax)
+ match
+ (?<!:)(:)(?>[a-zA-Z_]\w*(?>[?!])?)(?=\s*=>)
+ name
+ constant.other.symbol.hashkey.ruby
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(class)\b(?![?!])
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.class.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.class.end.ruby
+
+
+ name
+ meta.class.ruby
+ patterns
+
+
+ match
+ \G\s+(?:([.a-zA-Z0-9_:]+)(?:\s*(<)\s*([.a-zA-Z0-9_:]+))?|(<<)\s*([.a-zA-Z0-9_:]+))
+ captures
+
+ 1
+
+ name
+ entity.name.type.class.ruby
+ patterns
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.separator.namespace.ruby
+
+
+ comment
+ Mark as namespace separator if double colons followed by capital letter
+ match
+ (::)\s*(?=[A-Z])
+
+
+ include
+ $self
+
+
+
+ 2
+
+ name
+ keyword.operator.other.ruby
+
+ 3
+
+ name
+ entity.other.inherited-class.ruby
+ patterns
+
+
+ captures
+
+ 1
+
+ name
+ punctuation.separator.namespace.ruby
+
+
+ comment
+ Mark as namespace separator if double colons followed by capital letter
+ match
+ (::)\s*(?=[A-Z])
+
+
+ include
+ $self
+
+
+
+ 4
+
+ name
+ keyword.operator.other.ruby
+
+ 5
+
+ name
+ variable.other.object.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(module)\b(?![?!])
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.module.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.module.end.ruby
+
+
+ name
+ meta.module.ruby
+ patterns
+
+
+ match
+ \G\s+(([A-Z]\w*(::))?([A-Z]\w*(::))?([A-Z]\w*(::))*[A-Z]\w*)
+ captures
+
+ 1
+
+ name
+ entity.name.type.module.ruby
+
+ 2
+
+ name
+ entity.other.inherited-class.module.first.ruby
+
+ 3
+
+ name
+ punctuation.separator.inheritance.ruby
+
+ 4
+
+ name
+ entity.other.inherited-class.module.second.ruby
+
+ 5
+
+ name
+ punctuation.separator.inheritance.ruby
+
+ 6
+
+ name
+ entity.other.inherited-class.module.third.ruby
+
+ 7
+
+ name
+ punctuation.separator.inheritance.ruby
+
+
+
+
+ include
+ $self
+
+
+
+
+ comment
+ else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.
+ match
+ (?<!\.)\belse(\s)+if\b
+ name
+ invalid.deprecated.ruby
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(for)\b(?![?!])
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.for.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.for.end.ruby
+
+
+ name
+ meta.block.for.ruby
+ patterns
+
+
+ begin
+ \G\s+(.+?)\s+\b(in)\b
+ beginCaptures
+
+ 1
+
+ patterns
+
+
+ include
+ $self
+
+
+
+ 2
+
+ name
+ keyword.control.in.ruby
+
+
+ end
+ (?<![^.]\.|::)(\bdo\b)(?![?!])|(?=;|$)
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.optional.do.ruby
+
+
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(do)\b(?![?!])\s*(\|[^|]*\|)?
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.do.begin.ruby
+
+ 2
+
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.do.end.ruby
+
+
+ name
+ meta.block.do.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(begin)\b(?![?!])
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.begin.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.begin.end.ruby
+
+
+ name
+ meta.block.begin.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?<!^\.|[^.]\.|::)\b(case)\b(?![?!])
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.conditional.case.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.conditional.case.end.ruby
+
+
+ name
+ meta.block.case.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?x)
+ (?:
+ ^ # beginning of line
+ | (?<= # or look-behind on:
+ [=>~(?:\[,|&;]
+ | [\s;]if\s # keywords
+ | [\s;]elsif\s
+ | [\s;]while\s
+ | [\s;]unless\s
+ | [\s;]when\s
+ | [\s;]assert_match\s
+ | [\s;]or\s # boolean opperators
+ | [\s;]and\s
+ | [\s;]not\s
+ | [\s.]index\s # methods
+ | [\s.]scan\s
+ | [\s.]sub\s
+ | [\s.]sub!\s
+ | [\s.]gsub\s
+ | [\s.]gsub!\s
+ | [\s.]match\s
+ )
+ | (?<= # or a look-behind with line anchor:
+ ^when\s # duplication necessary due to limits of regex
+ | ^if\s
+ | ^elsif\s
+ | ^while\s
+ | ^unless\s
+ )
+ )
+ \s*((/))(?![*+{}?])
+
+ beginCaptures
+
+ 1
+
+ name
+ string.regexp.classic.ruby
+
+ 2
+
+ name
+ punctuation.definition.string.ruby
+
+
+ comment
+ regular expressions (normal)
+ we only start a regexp if the character before it (excluding whitespace)
+ is what we think is before a regexp
+
+ contentName
+ string.regexp.classic.ruby
+ end
+ ((/[eimnosux]*))(?:\s+(?:\b(if)|(unless)\b(?![?!]))|\s+(?:\b(while)|(until)\b(?![?!])))?
+ endCaptures
+
+ 1
+
+ name
+ string.regexp.classic.ruby
2
name
- entity.name.type.class.ruby
+ punctuation.definition.string.ruby
3
name
- keyword.operator.other.ruby
+ keyword.control.modifier.conditional.if.ruby
4
name
- entity.other.inherited-class.ruby
+ keyword.control.modifier.conditional.unless.ruby
5
name
- keyword.operator.other.ruby
+ keyword.control.modifier.while.ruby
6
name
- variable.other.object.ruby
+ keyword.control.modifier.until.ruby
+
+
+ patterns
+
+
+ include
+ #regex_sub
+
+
+
+
+ captures
+
+ 1
+
+ name
+ keyword.control.modifier.conditional.if.ruby
+
+ 2
+
+ name
+ keyword.control.modifier.conditional.unless.ruby
match
- ^\s*(class)\s+(?:([.a-zA-Z0-9_:]+)(?:\s*(<)\s*([.a-zA-Z0-9_:]+))?|(<<)\s*([.a-zA-Z0-9_:]+))
+ (?x)
+ (?=\s*if\b|\s*unless\b)
+ (?<=[}\])\w?!"'`])
+ \s*\b(if)|(unless)\b(?![?!])
+
+
+
+ begin
+ (?x)
+ (?=\s*if\b)
+ (?<!::)
+ (?<=<|&|\||=|>|~|\^|[+\-*/%]|\.{2}|\.{3}|^|;|:|\[|\(|\{|,|
+ \Wif|^if| # \WX|^X is equivalent to \bX
+ \Wunless|^unless| # this is workaround for code editors which doesn't support onigomo
+ \Wcase|^case| # https://github.com/microsoft/vscode-textmate/issues/121#issuecomment-565689295
+ \Wwhen|^when|
+ \Wwhile|^while|
+ \Wuntil|^until|
+ \Wfor|^for|
+ \Wbegin|^begin|
+ \Wand|^and|
+ \Wnot|^not|
+ \Wor|^or|
+ \Win|^in|
+ \W!|^!|
+ \W\?|^\?)
+ \s*\b(if)\b(?![?!:])
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.conditional.if.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.conditional.if.end.ruby
+
+
name
- meta.class.ruby
+ meta.block.if.ruby
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?x)
+ (?=\s*unless\b)
+ (?<!::)
+ (?<=<|&|\||=|>|~|\^|[+\-*/%]|\.{2}|\.{3}|^|;|:|\[|\(|\{|,|
+ \Wif|^if| # \WX|^X is equivalent to \bX
+ \Wunless|^unless| # this is workaround for code editors which doesn't support onigomo
+ \Wcase|^case| # https://github.com/microsoft/vscode-textmate/issues/121#issuecomment-565689295
+ \Wwhen|^when|
+ \Wwhile|^while|
+ \Wuntil|^until|
+ \Wfor|^for|
+ \Wbegin|^begin|
+ \Wand|^and|
+ \Wnot|^not|
+ \Wor|^or|
+ \Win|^in|
+ \W!|^!|
+ \W\?|^\?)
+ \s*\b(unless)\b(?![?!:])
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.conditional.unless.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.conditional.unless.end.ruby
+
+
+ name
+ meta.block.unless.ruby
+ patterns
+
+
+ include
+ $self
+
+
captures
@@ -149,104 +766,206 @@
1
name
- keyword.control.module.ruby
+ keyword.control.modifier.while.ruby
2
name
- entity.name.type.module.ruby
+ keyword.control.modifier.until.ruby
- 3
+
+ match
+ (?x)
+ (?=\s*while\b|\s*until\b)
+ (?<=[}\])\w?!"'`])
+ \s*\b(while)|(until)\b(?![?!])
+
+
+
+ begin
+ (?x)
+ (?=\s*while\b)
+ (?<!::)
+ (?<=<|&|\||=|>|~|\^|[+\-*/%]|\.{2}|\.{3}|^|;|:|\[|\(|\{|,|
+ \Wif|^if| # \WX|^X is equivalent to \bX
+ \Wunless|^unless| # this is workaround for code editors which doesn't support onigomo
+ \Wcase|^case| # https://github.com/microsoft/vscode-textmate/issues/121#issuecomment-565689295
+ \Wwhen|^when|
+ \Wwhile|^while|
+ \Wuntil|^until|
+ \Wfor|^for|
+ \Wbegin|^begin|
+ \Wand|^and|
+ \Wnot|^not|
+ \Wor|^or|
+ \Win|^in|
+ \W!|^!|
+ \W\?|^\?)
+ \s*\b(while)\b(?![?!:])
+
+ beginCaptures
+
+ 1
name
- entity.other.inherited-class.module.first.ruby
+ keyword.control.while.begin.ruby
- 4
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
name
- punctuation.separator.inheritance.ruby
+ keyword.control.end.ruby
- 5
+ 2
name
- entity.other.inherited-class.module.second.ruby
+ keyword.control.while.end.ruby
- 6
+
+ name
+ meta.block.while.ruby
+ patterns
+
+
+ begin
+ \G
+ end
+ (?<![^.]\.|::)(\bdo\b)(?![?!])|(?=;|$)
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.optional.do.ruby
+
+
+ patterns
+
+
+ include
+ $self
+
+
+
+
+ include
+ $self
+
+
+
+
+ begin
+ (?x)
+ (?=\s*until\b)
+ (?<!::)
+ (?<=<|&|\||=|>|~|\^|[+\-*/%]|\.{2}|\.{3}|^|;|:|\[|\(|\{|,|
+ \Wif|^if| # \WX|^X is equivalent to \bX
+ \Wunless|^unless| # this is workaround for code editors which doesn't support onigomo
+ \Wcase|^case| # https://github.com/microsoft/vscode-textmate/issues/121#issuecomment-565689295
+ \Wwhen|^when|
+ \Wwhile|^while|
+ \Wuntil|^until|
+ \Wfor|^for|
+ \Wbegin|^begin|
+ \Wand|^and|
+ \Wnot|^not|
+ \Wor|^or|
+ \Win|^in|
+ \W!|^!|
+ \W\?|^\?)
+ \s*\b(until)\b(?![?!:])
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.until.begin.ruby
+
+
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
name
- punctuation.separator.inheritance.ruby
+ keyword.control.until.end.ruby
- 7
+
+ name
+ meta.block.until.ruby
+ patterns
+
- name
- entity.other.inherited-class.module.third.ruby
+ begin
+ \G
+ end
+ (?<![^.]\.|::)(\bdo\b)(?![?!])|(?=;|$)
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.optional.do.ruby
+
+
+ patterns
+
+
+ include
+ $self
+
+
- 8
- name
- punctuation.separator.inheritance.ruby
+ include
+ $self
-
- match
- ^\s*(module)\s+(([A-Z]\w*(::))?([A-Z]\w*(::))?([A-Z]\w*(::))*[A-Z]\w*)
- name
- meta.module.ruby
+
- comment
- else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.
match
- (?<!\.)\belse(\s)+if\b
+ (?<!\.|::)\brescue\b(?![?!])
name
- invalid.deprecated.ruby
+ keyword.control.rescue.ruby
- captures
-
- 1
-
- name
- punctuation.definition.constant.ruby
-
-
- comment
- symbols as hash key (1.9 syntax)
match
- (?>[a-zA-Z_]\w*(?>[?!])?)(:)(?!:)
+ (?<!\.|::)\bensure\b(?![?!])
name
- constant.other.symbol.hashkey.ruby
+ keyword.control.ensure.ruby
- captures
-
- 1
-
- name
- punctuation.definition.constant.ruby
-
-
- comment
- symbols as hash key (1.8 syntax)
match
- (?<!:)(:)(?>[a-zA-Z_]\w*(?>[?!])?)(?=\s*=>)
+ (?<!\.|::)\b(else|elsif|when|then)\b(?![?!])
name
- constant.other.symbol.hashkey.ruby
+ keyword.control.conditional.$1.ruby
-
- comment
- everything being a reserved word, not a value and needing a 'end' is a..
+ comment
+
+ All structures that are closed with keyword 'end' already defined higher.
+ This rule is made to match freestanding 'end'.
+
match
- (?<!\.)\b(BEGIN|begin|case|class|else|elsif|END|end|ensure|for|if|in|module|rescue|then|unless|until|when|while)\b(?![?!])
+ (?<!\.|::)\bend\b(?![?!:])
name
- keyword.control.ruby
+ keyword.control.end.ruby
- comment
- contextual smart pair support for block parameters
match
- (?<!\.)\bdo\b
+ (?<!\.)\b(BEGIN|END)\b(?![?!])
name
- keyword.control.start-block.ruby
+ keyword.control.$1.ruby
comment
@@ -274,42 +993,6 @@
name
variable.language.ruby
-
- begin
- ^__END__\n
- captures
-
- 0
-
- name
- string.unquoted.program-block.ruby
-
-
- comment
- __END__ marker
- contentName
- text.plain
- end
- (?=not)impossible
- patterns
-
-
- begin
- (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
- end
- (?=not)impossible
- name
- text.html.embedded.ruby
- patterns
-
-
- include
- text.html.basic
-
-
-
-
-
match
\b(self)\b(?![?!])
@@ -447,19 +1130,19 @@
begin
(?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\s+ # the def keyword
- ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
- |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
- \s*(\() # the openning parenthesis for arguments
-
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\s+ # the def keyword
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
+ \s*(\() # the openning parenthesis for arguments
+
beginCaptures
1
name
- keyword.control.def.ruby
+ keyword.control.def.begin.ruby
2
@@ -475,13 +1158,18 @@
comment
the method pattern comes from the symbol pattern, see there for a explaination
end
- \)
+ (?<!\.|::)\b((end))\b(?![?!:])
endCaptures
- 0
+ 1
name
- punctuation.definition.parameters.ruby
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.def.end.ruby
name
@@ -490,86 +1178,31 @@
begin
- (?=[&*_a-zA-Z])
- end
- (?=[,)])
- patterns
-
-
- captures
-
- 1
-
- name
- storage.type.variable.ruby
-
- 2
-
- name
- constant.other.symbol.hashkey.parameter.function.ruby
-
- 3
-
- name
- punctuation.definition.constant.ruby
-
- 4
-
- name
- variable.parameter.function.ruby
-
-
- match
- \G([&*]?)(?:([_a-zA-Z]\w*(:))|([_a-zA-Z]\w*))
-
-
- include
- #parens
-
-
- include
- #braces
-
-
- include
- $self
-
-
-
-
- repository
-
- braces
-
- begin
- \{
- beginCaptures
-
- 0
-
- name
- punctuation.section.function.begin.ruby
-
-
+ \G(?<=\()
end
- \}
+ \)
endCaptures
0
name
- punctuation.section.function.end.ruby
+ punctuation.definition.parameters.ruby
patterns
- include
- #parens
-
-
- include
- #braces
+ begin
+ (?=[&*_a-zA-Z])
+ end
+ (?=[,)])
+ patterns
+
+
+ include
+ #method_parameters
+
+
include
@@ -577,63 +1210,29 @@
- parens
- begin
- \(
- beginCaptures
-
- 0
-
- name
- punctuation.section.function.begin.ruby
-
-
- end
- \)
- endCaptures
-
- 0
-
- name
- punctuation.section.function.end.ruby
-
-
- patterns
-
-
- include
- #parens
-
-
- include
- #braces
-
-
- include
- $self
-
-
+ include
+ $self
-
+
begin
(?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\s+ # the def keyword
- ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
- |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
- [ \t] # the space separating the arguments
- (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow
-
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\s+ # the def keyword
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method
+ [ \t] # the space separating the arguments
+ (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow
+
beginCaptures
1
name
- keyword.control.def.ruby
+ keyword.control.def.begin.ruby
2
@@ -644,46 +1243,43 @@
comment
same as the previous rule, but without parentheses around the arguments
end
- $
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
+
+ 1
+
+ name
+ keyword.control.end.ruby
+
+ 2
+
+ name
+ keyword.control.def.end.ruby
+
+
name
meta.function.method.with-arguments.ruby
patterns
begin
- (?![\s,])
+ \G(?<=[ \t])
end
- (?=,|$)
+ (?=;)|(?<=[\w\])}`'"!?])(?=\s*#|\s*$)
patterns
- captures
-
- 1
-
- name
- storage.type.variable.ruby
-
- 2
-
- name
- constant.other.symbol.hashkey.parameter.function.ruby
-
- 3
-
- name
- punctuation.definition.constant.ruby
-
- 4
+ begin
+ (?=[&*_a-zA-Z])
+ end
+ (?=,|;|\s*#|\s*$)
+ patterns
+
- name
- variable.parameter.function.ruby
+ include
+ #method_parameters
-
- match
- \G([&*]?)(?:([_a-zA-Z]\w*(:))|([_a-zA-Z]\w*))
- name
- variable.parameter.function.ruby
+
include
@@ -691,35 +1287,61 @@
+
+ include
+ $self
+
- captures
+ begin
+ (?x)
+ (?=def\b) # an optimization to help Oniguruma fail fast
+ (?<=^|\s)(def)\b # the def keyword
+ ( \s+ # an optional group of whitespace followed by…
+ ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
+ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
+ |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) )? # …or an operator method
+
+ beginCaptures
+
+ 1
+
+ name
+ keyword.control.def.begin.ruby
+
+ 3
+
+ name
+ entity.name.function.ruby
+
+
+ comment
+ the optional name is just to catch the def also without a method-name
+ end
+ (?<!\.|::)\b((end))\b(?![?!:])
+ endCaptures
1
name
- keyword.control.def.ruby
+ keyword.control.end.ruby
- 3
+ 2
name
- entity.name.function.ruby
+ keyword.control.def.end.ruby
- comment
- the optional name is just to catch the def also without a method-name
- match
- (?x)
- (?=def\b) # an optimization to help Oniguruma fail fast
- (?<=^|\s)(def)\b # the def keyword
- ( \s+ # an optional group of whitespace followed by…
- ( (?>[a-zA-Z_]\w*(?>\.|::))? # a method name prefix
- (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name
- |===?|!=|!~|>[>=]?|<=>|<[<=]?|[%&`/\|^]|\*\*?|=?~|[-+]@?|\[\]=?) ) )? # …or an operator method
-
name
meta.function.method.without-arguments.ruby
+ patterns
+
+
+ include
+ $self
+
+
match
@@ -924,70 +1546,6 @@
include
#percent_literals
-
- begin
- (?x)
- (?:
- ^ # beginning of line
- | (?<= # or look-behind on:
- [=>~(?:\[,|&;]
- | [\s;]if\s # keywords
- | [\s;]elsif\s
- | [\s;]while\s
- | [\s;]unless\s
- | [\s;]when\s
- | [\s;]assert_match\s
- | [\s;]or\s # boolean opperators
- | [\s;]and\s
- | [\s;]not\s
- | [\s.]index\s # methods
- | [\s.]scan\s
- | [\s.]sub\s
- | [\s.]sub!\s
- | [\s.]gsub\s
- | [\s.]gsub!\s
- | [\s.]match\s
- )
- | (?<= # or a look-behind with line anchor:
- ^when\s # duplication necessary due to limits of regex
- | ^if\s
- | ^elsif\s
- | ^while\s
- | ^unless\s
- )
- )
- \s*((/))(?![*+{}?])
-
- captures
-
- 1
-
- name
- string.regexp.classic.ruby
-
- 2
-
- name
- punctuation.definition.string.ruby
-
-
- comment
- regular expressions (normal)
- we only start a regexp if the character before it (excluding whitespace)
- is what we think is before a regexp
-
- contentName
- string.regexp.classic.ruby
- end
- ((/[eimnosux]*))
- patterns
-
-
- include
- #regex_sub
-
-
-
captures
@@ -1058,34 +1616,70 @@
comment
- matches questionmark-letters.
-
- examples (1st alternation = hex):
- ?\x1 ?\x61
-
- examples (2nd alternation = octal):
- ?\0 ?\07 ?\017
-
- examples (3rd alternation = escaped):
- ?\n ?\b
-
- examples (4th alternation = meta-ctrl):
- ?\C-a ?\M-a ?\C-\M-\C-\M-a
-
- examples (4th alternation = normal):
- ?a ?A ?0
- ?* ?" ?(
- ?. ?#
+ matches questionmark-letters.
+ examples (1st alternation = hex):
+ ?\x1 ?\x61
- the negative lookbehind prevents against matching
- p(42.tainted?)
-
+ examples (2nd alternation = octal):
+ ?\0 ?\07 ?\017
+
+ examples (3rd alternation = escaped):
+ ?\n ?\b
+
+ examples (4th alternation = meta-ctrl):
+ ?\C-a ?\M-a ?\C-\M-\C-\M-a
+
+ examples (4th alternation = normal):
+ ?a ?A ?0
+ ?* ?" ?(
+ ?. ?#
+
+
+ the negative lookbehind prevents against matching
+ p(42.tainted?)
+
match
(?<!\w)\?(\\(x\h{1,2}(?!\h)\b|0[0-7]{0,2}(?![0-7])\b|[^x0MC])|(\\[MC]-)+\w|[^\s\\])
name
constant.numeric.ruby
+
+ begin
+ ^__END__\n
+ captures
+
+ 0
+
+ name
+ string.unquoted.program-block.ruby
+
+
+ comment
+ __END__ marker
+ contentName
+ text.plain
+ end
+ (?=not)impossible
+ patterns
+
+
+ begin
+ (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
+ end
+ (?=not)impossible
+ name
+ text.html.embedded.ruby
+ patterns
+
+
+ include
+ text.html.basic
+
+
+
+
+
begin
(?=(?><<[-~]("?)((?:[_\w]+_|)HTML)\b\1))
@@ -1726,17 +2320,17 @@
begin
- (?>=\s*<<(\w+))
+ (?<==)\s*(<<(\w+))
beginCaptures
- 0
+ 1
name
punctuation.definition.string.begin.ruby
end
- ^\1$
+ ^\2$
endCaptures
0
@@ -1806,7 +2400,7 @@
begin
- (?<=\{|do|\{\s|do\s)(\|)
+ (?<=\{|\sdo|\{\s|\sdo\s)(\|)
captures
1
@@ -1988,6 +2582,189 @@
repository
+ method_parameters
+
+ patterns
+
+
+ include
+ #params
+
+
+ include
+ #parens
+
+
+ include
+ #braces
+
+
+ include
+ #brackets
+
+
+ include
+ $self
+
+
+ repository
+
+ params
+
+ captures
+
+ 1
+
+ name
+ storage.type.variable.ruby
+
+ 2
+
+ name
+ constant.other.symbol.hashkey.parameter.function.ruby
+
+ 3
+
+ name
+ punctuation.definition.constant.ruby
+
+ 4
+
+ name
+ variable.parameter.function.ruby
+
+
+ match
+ \G(&|\*\*?)?(?:([_a-zA-Z]\w*(:))|([_a-zA-Z]\w*))
+
+ braces
+
+ begin
+ \{
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.section.scope.begin.ruby
+
+
+ end
+ \}
+ endCaptures
+
+ 0
+
+ name
+ punctuation.section.scope.end.ruby
+
+
+ patterns
+
+
+ include
+ #parens
+
+
+ include
+ #braces
+
+
+ include
+ #brackets
+
+
+ include
+ $self
+
+
+
+ brackets
+
+ begin
+ \[
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.section.array.begin.ruby
+
+
+ end
+ \]
+ endCaptures
+
+ 0
+
+ name
+ punctuation.section.array.end.ruby
+
+
+ patterns
+
+
+ include
+ #parens
+
+
+ include
+ #braces
+
+
+ include
+ #brackets
+
+
+ include
+ $self
+
+
+
+ parens
+
+ begin
+ \(
+ beginCaptures
+
+ 0
+
+ name
+ punctuation.section.function.begin.ruby
+
+
+ end
+ \)
+ endCaptures
+
+ 0
+
+ name
+ punctuation.section.function.end.ruby
+
+
+ patterns
+
+
+ include
+ #parens
+
+
+ include
+ #braces
+
+
+ include
+ #brackets
+
+
+ include
+ $self
+
+
+
+
+
escaped_char
match
diff --git a/Tests/end_distinction.rb b/Tests/end_distinction.rb
new file mode 100644
index 0000000..f9b1c50
--- /dev/null
+++ b/Tests/end_distinction.rb
@@ -0,0 +1,763 @@
+# -------------------------------------------
+# Testarea for classes
+# -------------------------------------------
+
+# singleline
+class F; end
+class F end
+(class F end)
+
+
+class Foo; @@a = 1; end
+class Foo::Bar < M::Baz; @@a = 1; end
+class A class B end end
+class A; class B; end; end
+
+# multiline
+class Foo
+ @@var = 1
+
+ $class = "myclass"
+ @@module = "mymodule"
+ class_name = "class_name"
+ module_name = "module_name"
+ self.class.methods
+ self::class::methods
+
+ def module
+ nil
+ end
+
+ def class
+ nil
+ end
+end
+
+Foo.new.module
+Foo.new::module
+Foo.new.class
+Foo.new::class
+
+# -------------------------------------------
+# Testarea for classes
+# -------------------------------------------
+
+# singleline
+module Mod; @a = 1; end
+module ModOne::ModTwo; @a = 1; end
+module M module N end end
+module M; module N end end
+(module M module N end end)
+
+# multiline
+module Bar
+ $class = "myclass"
+ @module = "mymodule"
+ class_name = "class_name"
+ module_name = "module_name"
+ class Foo
+ @@var = 1
+ end
+end
+
+# -------------------------------------------
+# Testarea for method without arguments
+# -------------------------------------------
+
+# singleline
+def a; puts "a"; end
+def b; def c; puts "c"; end; end
+def d; puts self.end; end
+def method; hello, world = [1,2] end # test comment
+
+# multiline
+def e
+ puts "e"
+end
+
+def f
+ def g
+ puts "g"
+ end
+end
+
+def h
+ puts self.end
+end
+
+def i
+ end? # self.end?
+ end! # self.end!
+end
+
+def method # test comment
+ hello, world = [1,2]
+end
+
+# -------------------------------------------
+# Testarea for method with arguments
+# -------------------------------------------
+
+# singleline
+def a(arg); puts arg; end
+def b; def c(arg); puts arg; end; end
+def d(arg); puts arg.end; end
+def method_with_parentheses(*a, **b, &c) hello, world = [1,2] end # test comment
+def method_with_parentheses(a, b, c = [foo,bar,baz]) hello, world = [1,2] end # test comment
+
+# multiline
+def e(arg)
+ puts arg
+end
+
+def f
+ def g(arg)
+ puts arg
+ end
+end
+
+def h(arg)
+ puts arg.end
+end
+
+def i(arg)
+ end? # self.end?
+ end! # self.end!
+end
+
+def method_with_parentheses(a, b, c = [foo,bar,baz]) # test comment
+ hello, world = [1,2]
+end
+
+def method_with_parentheses(a, b = "hello", c = ["foo", "bar"], d = (2 + 2) * 2, e = {}) # test comment
+ hello, world = [1,2]
+ do_something1
+ do_something2
+end
+
+def method_with_parentheses(a,
+ b = hello, # test comment
+ c = ["foo", bar, :baz],
+ d = (2 + 2) * 2,
+ e = {})
+ hello, world = [1,2]
+ do_something1
+ do_something2
+end
+
+# -------------------------------------------
+# Testarea for method with arguments without parenthesis
+# -------------------------------------------
+
+# singleline
+def a arg; puts arg; end
+def b; def c arg; puts arg; end; end
+def d arg; puts arg.end; end
+def method_without_parentheses a, b, c = [foo,bar,baz]; hello, world = [1,2] end # test comment
+def method_without_parentheses *a, **b, &c; hello, world = [1,2] end # test comment
+
+# multiline
+def e arg
+ puts arg
+end
+
+def f
+ def g arg
+ puts arg
+ end
+end
+
+def h arg
+ puts arg.end
+end
+
+def i arg
+ end? # self.end?
+ end! # self.end!
+end
+
+def method_without_parentheses a, b, c = [foo,bar,baz] # test comment
+ hello, world = [1,2]
+end
+
+def method_without_parentheses a, b = "hello", c = ["foo", "bar"], d = (2 + 2) * 2, e = "" # test comment
+ hello, world = [1,2]
+ do_something1
+ do_something2
+end
+
+def method_without_parentheses a,
+ b = "hello" , # test comment
+ c = ["foo", bar, :baz],
+ d = (2 + 2) * 2,
+ e = proc { |e| e + e }
+ hello, world = [1,2]
+ do_something1
+ do_something2
+end
+
+def method_without_parentheses *a, **b, &c # test comment
+ hello, world = [1,2]
+end
+
+# -------------------------------------------
+# Testarea for begin-block
+# -------------------------------------------
+
+# singleline
+begin puts "foo" end
+begin puts "foo"; begin puts "bar" end end
+begin puts self.end end
+begin puts self.end; end
+begin puts end? end
+begin puts end!; end
+if begin true end then true else false end
+1..begin 10 end
+1...begin 10 end
+
+self.begin puts "foo" end #shouldn't work
+self::begin puts "foo" end #shouldn't work
+begin? puts "foo" end #shouldn't work
+begin! puts "foo" end #shouldn't work
+
+# multiline
+begin
+ puts "foo"
+end
+
+begin
+ puts self.end
+end
+
+begin
+ puts end?
+ puts end!
+end
+
+begin
+ puts "foo"
+ begin
+ puts "bar"
+ end
+end
+
+# -------------------------------------------
+# Testarea for do-block
+# -------------------------------------------
+
+# singleline
+3.times.map do 1 end
+3.times.map do || 1 end
+3.times.map do |e, x=1| e + x end
+[(0..10), (10..20)].map do |r| r.end end
+any_method do? 1 end #shouldn't work
+any_method do! 1 end #shouldn't work
+self.do 1 end #shouldn't work
+self::do 1 end #shouldn't work
+
+# multiline
+[1,2,3].map do |element|
+ element + 1
+end
+
+[[1],[2],[3]].each do |element|
+ element.each do |subelement|
+ puts subelement
+ end
+end
+
+[(0..10), (10..20)].map do |r|
+ r.end
+end
+
+[].each do |e|
+ e + end? - end!
+end
+
+3.times do
+ puts "foo"
+end
+
+3.times do ||
+ puts "bar"
+end
+
+def test
+ @do ||= {}
+end
+
+# -------------------------------------------
+# Testarea for for-loop
+# -------------------------------------------
+
+# singleline
+for i in for j in [[1,2]] do break j; end do puts i; end
+for i in for j in [[1,2]] do break j; end do [i].map do |e| e end; end
+for i in for j in [[1,2]]; break j; end; [i].map do |e| e end; end
+for i in for j in if true then [[1,2]] else [[3,4]] end; break j; end; [i].map do |e| e end; end
+for i in for j in if true; [[1,2]] else [[3,4]] end; break j; end; [i].map do |e| e end; end
+for i in [(0..10), (10..20)] do break i.end end
+for i in [] do puts end?; puts end! end
+1..for i in [1,2,3] do break i if i == 2; end
+1...for i in [1,2,3] do break i if i == 2; end
+10 / for i in [1,2,3] do break i if i == 2; end
+[for i in [1,2,3] do break i if i == 2 end]
+[ for i in [1,2,3] do break i if i == 2 end, for i in [1,2,3] do break i if i == 3 end]
+{for i in [1,2,3] do break i if i == 2 end => 1}
+{ for i in [1,2,3] do break i if i == 2 end => 1 }
+{foo: for i in [1,2,3] do break i if i == 2 end}
+{ foo: for i in [1,2,3] do break i if i == 2 end, bar: for i in [1,2,3] do break i if i == 3 end }
+{:foo => for i in [1,2,3] do break i if i == 2 end}
+{ :foo => for i in [1,2,3] do break i if i == 2 end, :bar=>for i in [1,2,3] do break i if i == 3 end }
+(for i in [1,2,3] do break i if i == 2 end)
+( for i in [1,2,3] do break i if i == 2 end )
+
+#you cant use do-end blocks inside in statement
+for i in 3.times.map do 1 end do puts i; end # shouldn't work
+for? i in [1,2,3] # shouldn't work
+for! i in [1,2,3] # shouldn't work
+self.for i in [1,2,3] # shouldn't work
+
+# multiline
+for i in [1,2,3]
+ puts i
+end
+
+for i in [(0..10), (10..20)] do
+ puts i.end
+end
+
+for i in []
+ puts end?
+ puts end!
+end
+
+for i in for j in [[1,2]] do break j; end do
+ r = [i].map do |e|
+ e
+ end
+ p r
+end
+
+# -------------------------------------------
+# Testarea for while/until
+# -------------------------------------------
+
+# singleline block
+i = 0
+while i < 10; i += 1; end
+while i < 10 do i += 1; end
+a = while i < 10 do break i if i == 5; i += 1; end
+false || while i < 10 do break i if i == 5; i += 1; end
+false or while i < 10; break i if i == 5; i += 1; end
+true && while i < 10; break i if i == 5; i += 1; end
+true and while i < 10 do break i if i == 5; i += 1; end
+1..while i < 10 do break i if i == 5; i += 1; end
+1...while i < 10 do break i if i == 5; i += 1; end
+true ? while i < 10; break i if i == 5; i += 1; end : while i < 10; break i if i == 5; i += 1; end
+!while i < 10; break i if i == 5; i += 1; end
+! while i < 10; break i if i == 5; i += 1; end
+true && !while i < 10; break i if i == 5; i += 1; end
+true && ! while i < 10; break i if i == 5; i += 1; end
+while i < while j < 10; break j if j == 5; j+=1; end; break i if i > 3; i += 1; end
+while i < while j < 10 do break j if j == 5; j+=1; end; break i if i > 3; i += 1; end
+while i < while j < 10; break j if j == 5; j+=1; end do break i if i > 3; i += 1; end
+while i < while j < 10 do break j if j == 5; j+=1; end do break i if i > 3; i += 1; end
+while false do [1,2,3].each do |e| puts e end; end
+while false do [(0..10), (10..20)].each do |r| puts r.end end end
+while false do puts end?; puts end! end
+[while i < 10 do break i if i == 5; i += 1; end]
+[ while i < 10 do break i if i == 5; i += 1 end, while i < 10 do break i if i == 6; i += 1 end ]
+{while i < 10 do break i if i == 5; i += 1 end => 1}
+{ while i < 10 do break i if i == 5; i += 1 end => 1 }
+{foo: while i < 10 do break i if i == 5; i += 1 end}
+{ foo: while i < 10 do break i if i == 5; i += 1 end, bar:while i < 10 do break i if i == 6; i += 1 end }
+{:foo => while i < 10 do break i if i == 5; i += 1 end}
+{ :foo => while i < 10 do break i if i == 5; i += 1 end, :bar=>while i < 10 do break i if i == 6; i += 1 end }
+(while i < 10 do break i if i == 5; i += 1 end)
+( while i < 10 do break i if i == 5; i += 1 end )
+
+# singleline modifier
+foo::while false # shouldn't work
+while? false # shouldn't work
+while! false # shouldn't work
+foo.while false # shouldn't work
+acc = 0
+acc += 10 while acc < 1000
+a = /regex/ while acc < 10
+{} while false
+[] while false
+"foo" while false
+'foo' while false
+(expression) while false
+foo! while false
+foo? while false
+method_without_args while false
+method(with, args) while false
+method with, args while false
+`ls` while false
+
+# multiline block
+while i < 10
+ i += 1
+end
+
+while i < 10 do
+ i += 1
+end
+
+10 / while i < 10 do
+ break i if i == 5
+ i += 1
+end
+
+while false do
+ [(0..10), (10..20)].each do |r|
+ puts r.end
+ end
+end
+
+while false do
+ puts end?
+ puts end!
+end
+
+begin
+ i += 1
+end; while i < 100 do i += 1; end
+
+# multiline modifier
+begin
+ i += 1
+end while i < 100
+
+# -------------------------------------------
+# Testarea for if/unless
+# -------------------------------------------
+
+# singleline block
+1..if true; 10 else 20 end
+1...if true then 10 else 20 end
+if while i < 10 do break i if i == 5; i += 1; end < 10 then true else false end
+if true then 1 else 2 end
+true ? if true then true else false end : if true then true else false end
+if if true then true else false end; 1 else 0 end
+if if true then true else false end then 1 else 0 end
+if if true; true else false end then 1 else 0 end
+if if true; true else false end; 1 else 0 end
+20 / if true then 10 else 5 end
+20 / if true; 10 else 5 end
+!if true then true else false end
+! if true then true else false end
+true && !if true then true else false end
+true && ! if true then true else false end
+a = /hello/; 20 / if true then 1 else 2 end
+a = /hello/; if true then 1 else 2 end
+if true then puts (1..10).end else puts (1..20).end end
+if true then puts end? else puts end! end
+[if true then 1 else 2 end]
+[ if true then 1 else 2 end, if true then 2 else 3 end]
+{if true then :foo else :bar end => 1}
+{ if true then :foo else :bar end => 1 }
+{foo: if true then 1 else 2 end}
+{ foo: if true then 1 else 2 end, bar: if true then 2 else 3 end }
+{:foo => if true then 1 else 2 end}
+{ :foo => if true then 1 else 2 end, :bar=>if true then 2 else 3 end }
+(if true then 1 else 2 end)
+( if true then 1 else 2 end )
+
+# singleline modifier
+foo::if something # shouldn't work
+foo.if something # shouldn't work
+if? something # shouldn't work
+if! something # shouldn't work
+foo! if true
+foo? if true
+return {} if something
+return [] if something
+(expression) if something
+method_without_args if something
+method(with, args) if something
+method with, args if somethign
+a = /regexp/ if something
+"hello".scan /[eo]/ if something
+`ls` if true
+
+# singleline mix
+%w(hello, world, foo).map { |e| e.scan /[oeiua]/ } * if true; 2 else 0 end
+%w(hello, world, foo).map { |e| e.scan /[oeiua]/ if true } * if true then 2 else 0 end
+e.scan /[oeiua]/ if true; if true then 2 else 0 end
+
+# multiline block
+if something then
+ if true
+ foo
+ else
+ bar
+ end
+else
+ baz
+end
+
+if true
+ puts (1..10).end
+else
+ puts (1..20).end
+end
+
+if true
+ puts end?
+else
+ puts end!
+end
+
+begin
+ 1
+end; if true; true else false end
+
+# multiline modifier
+begin
+ 1
+end if true
+
+# -------------------------------------------
+# Testarea for case
+# -------------------------------------------
+
+# singleline
+case 15 when 0..50 then "foo" when 51..100 then "bar" else "baz" end
+case x = rand(1..100) when 0..50 then case x when 0..25 then 1 else 2 end when 51..100 then case x when 51..75 then 3 else 4 end end
+1..case 15 when 0..50 then 10 when 51..100 then 20 else 30 end
+1...case 15 when 0..50 then 10 when 51..100 then 20 else 30 end
+case x = rand(1..100) when 0..50 then puts (1..10).end when 51..100 then puts (1..20).end end
+case x = rand(1..100) when 0..50 then puts end? when 51..100 then puts end! end
+[case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end]
+[ case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end, case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end]
+{case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end => 1}
+{ case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end => 1 }
+{foo: case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end}
+{ foo: case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end, bar: case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end }
+{:foo => case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end}
+{ :foo => case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end, :bar=>case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end }
+(case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end)
+( case x = rand(1..100) when 0..50 then (1..10).end when 51..100 then (1..20).end end )
+
+self.case 15 when 0..50 then "foo" when 51..100 then "bar" else "baz" end # shouldn't work
+self::case 15 when 0..50 then "foo" when 51..100 then "bar" else "baz" end # shouldn't work
+case? 15 when 0..50 then "foo" when 51..100 then "bar" else "baz" end # shouldn't work
+case! 15 when 0..50 then "foo" when 51..100 then "bar" else "baz" end # shouldn't work
+
+# multiline
+case 15
+when 0..50
+ "foo"
+when 51..100
+ "bar"
+else
+ "baz"
+end
+
+case x = rand(1..100)
+when 0..50 then
+ puts (1..10).end
+when 51..100 then
+ puts (1..20).end
+end
+
+case x = rand(1..100)
+when 0..50 then
+ puts end?
+when 51..100 then
+ puts end!
+end
+
+
+case if [true, false].sample then 25 else 75 end
+when 0..50
+ "foo"
+when 51..100
+ "bar"
+else
+ "baz"
+end
+
+case x = rand(1..100)
+when 0..50 then
+ case x
+ when 0..25 then
+ 1
+ else
+ 2
+ end
+when 51..100 then
+ case x
+ when 51..75 then
+ 3
+ else
+ 4
+ end
+end
+
+# -------------------------------------------
+# Testarea for rescue & ensure
+# -------------------------------------------
+
+# singleline
+some_method rescue handle_error
+some_method rescue SomeException
+
+self.rescue handle_error # shouldn't work
+self::rescue handle_error # shouldn't work
+some_method rescue? handle_error # shouldn't work
+some_method rescue! SomeException # shouldn't work
+
+# multiline
+begin
+ some_method
+rescue
+ handle_error
+ensure
+ close_connection
+end
+
+begin
+ some_method
+rescue SomeException
+ handle_error
+ensure
+ close_connection
+end
+
+def method1
+ some_method
+rescue
+ handle_error
+ensure
+ close_connection
+end
+
+def method2
+ some_method
+rescue SomeException => e
+ log(e)
+ handle_error
+ensure
+ close_connection
+end
+
+def method3
+ some_method
+rescue? SomeException => e # shouldn't work
+ log(e)
+ handle_error
+ensure? # shouldn't work
+ close_connection
+end
+
+def method4
+ some_method
+rescue! SomeException => e # shouldn't work
+ log(e)
+ handle_error
+ensure! # shouldn't work
+ close_connection
+end
+
+def method5
+ some_method
+.rescue SomeException => e # shouldn't work
+ log(e)
+ handle_error
+.ensure # shouldn't work
+ close_connection
+end
+
+def method6
+ some_method
+::rescue SomeException => e # shouldn't work
+ log(e)
+ handle_error
+::ensure # shouldn't work
+ close_connection
+end
+
+# -------------------------------------------
+# Testarea for symbols that looks like keyword
+# -------------------------------------------
+
+{
+ class: 1,
+ module: 1,
+ if: 1,
+ unless: 1,
+ while: 1,
+ until: 1,
+ end: 1,
+ for: 1,
+ begin: 1,
+ or: 1,
+ not: 1,
+ in: 1,
+ when: 1,
+ then: 1,
+ case: 1,
+ else: 1,
+ do: 1,
+ rescue: 1,
+ ensure: 1,
+ elsif: 1,
+ def: 1
+}
+
+{class: 1,module: 1,if: 1,unless: 1,while: 1,until: 1,end: 1,for: 1,begin: 1,or: 1,not: 1,in: 1,when: 1,then: 1,case: 1,else: 1,do: 1,rescue: 1,ensure: 1,elsif: 1,def: 1}
+{ class: 1, module: 1, if: 1, unless: 1, while: 1, until: 1, end: 1, for: 1, begin: 1, or: 1, not: 1, in: 1, when: 1, then: 1, case: 1, else: 1, do: 1, rescue: 1, ensure: 1, elsif: 1, def: 1 }
+
+{
+ :class => 1,
+ :module => 1,
+ :if => 1,
+ :unless => 1,
+ :while => 1,
+ :until => 1,
+ :end => 1,
+ :for => 1,
+ :begin => 1,
+ :or => 1,
+ :not => 1,
+ :in => 1,
+ :when => 1,
+ :then => 1,
+ :case => 1,
+ :else => 1,
+ :do => 1,
+ :rescue => 1,
+ :ensure => 1,
+ :elsif => 1,
+ :def => 1,
+}
+
+[
+ :class,
+ :module,
+ :if,
+ :unless,
+ :until,
+ :end,
+ :for,
+ :begin,
+ :or,
+ :not,
+ :in,
+ :when,
+ :then,
+ :case,
+ :else,
+ :do,
+ :rescue,
+ :ensure,
+ :elsif,
+ :def
+]
+
+[:class,:module,:if,:unless,:until,:end,:for,:begin,:or,:not,:in,:when,:then,:case,:else,:do,:rescue,:ensure,:elsif,:def]
+[ :class, :module, :if, :unless, :until, :end, :for, :begin, :or, :not, :in, :when, :then, :case, :else, :do, :rescue, :ensure, :elsif, :def ]