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 ]