Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Commit

Permalink
Merge pull request #234 from cbothner/multiline-yard
Browse files Browse the repository at this point in the history
Support multiline YARD comments
  • Loading branch information
darangi authored Feb 4, 2021
2 parents 484326a + 933c9d4 commit dd2de8e
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 80 deletions.
151 changes: 109 additions & 42 deletions grammars/ruby.cson
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,9 @@
'end': '^=end'
'name': 'comment.block.documentation.ruby'
}
{
'include': '#yard'
}
{
'begin': '(^[ \\t]+)?(?=#)'
'beginCaptures':
Expand All @@ -1372,11 +1375,6 @@
'name': 'punctuation.definition.comment.ruby'
'end': '\\n'
'name': 'comment.line.number-sign.ruby'
'patterns': [
{
'include': '#yard'
}
]
}
]
}
Expand Down Expand Up @@ -2286,7 +2284,6 @@
}
]
'yard':
'name': 'comment.line.yard.ruby'
'patterns': [
{
'include': '#yard_comment'
Expand All @@ -2306,77 +2303,147 @@
]
'yard_comment':
'comment': 'For YARD tags that follow the tag-comment pattern'
'match': '(@)(abstract|api|author|deprecated|example|note|overload|since|todo|version)(?=\\s)(.*)$'
'captures':
'begin': '^(\\s*)(#)(\\s*)(@)(abstract|api|author|deprecated|example|macro|note|overload|since|todo|version)(?=\\s|$)'
'beginCaptures':
'1':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'name': ''
'2':
'name': 'comment.line.keyword.yard.ruby'
'name': 'punctuation.definition.comment.ruby'
'3':
'name': 'comment.line.string.yard.ruby'
'name': ''
'4':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'5':
'name': 'comment.line.keyword.yard.ruby'
'end': '^(?!\\s*#\\3\\s{2,})'
'contentName': 'comment.line.string.yard.ruby'
'name': 'comment.line.number-sign.ruby'
'patterns': [
{
'include': '#yard'
}
{
'include': '#yard_continuation'
}
]
'yard_name_types':
'comment': 'For YARD tags that follow the tag-name-types-comment pattern'
'match': '(@)(attr|attr_reader|attr_writer|option|param|see|yieldparam)(?=\\s)(\\s+([a-z_][a-zA-Z_]*))?(\\s+((\\[).+(])))?(.*)$'
'captures':
'begin': '^(\\s*)(#)(\\s*)(@)(attr|attr_reader|attr_writer|option|param|see|yieldparam)(?=\\s)(\\s+([a-z_][a-zA-Z_]*))?(\\s+((\\[).+(])))?'
'beginCaptures':
'1':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'name': ''
'2':
'name': 'comment.line.keyword.yard.ruby'
'name': 'punctuation.definition.comment.ruby'
'3':
'name': 'comment.line.yard.ruby'
'name': ''
'4':
'name': 'comment.line.parameter.yard.ruby'
'name': 'comment.line.keyword.punctuation.yard.ruby'
'5':
'name': 'comment.line.yard.ruby'
'name': 'comment.line.keyword.yard.ruby'
'6':
'name': 'comment.line.type.yard.ruby'
'name': 'comment.line.yard.ruby'
'7':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.parameter.yard.ruby'
'8':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.yard.ruby'
'9':
'name': 'comment.line.string.yard.ruby'
'name': 'comment.line.type.yard.ruby'
'10':
'name': 'comment.line.punctuation.yard.ruby'
'11':
'name': 'comment.line.punctuation.yard.ruby'
'end': '^(?!\\s*#\\3\\s{2,})'
'contentName': 'comment.line.string.yard.ruby'
'name': 'comment.line.number-sign.ruby'
'patterns': [
{
'include': '#yard'
}
{
'include': '#yard_continuation'
}
]
'yard_tag':
'comment': 'For YARD tags that are just the tag'
'match': '(@)(private)$'
'match': '^(\\s*)(#)(\\s*)(@)(private)$'
'captures':
'1':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'name': ''
'2':
'name': 'punctuation.definition.comment.ruby'
'3':
'name': ''
'4':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'5':
'name': 'comment.line.keyword.yard.ruby'
'name': 'comment.line.number-sign.ruby'
'yard_types':
'comment': 'For YARD tags that follow the tag-types-comment pattern'
'match': '(@)(raise|return|yield(?:return)?)(?=\\s)(\\s+((\\[).+(])))?(.*)$'
'captures':
'begin': '^(\\s*)(#)(\\s*)(@)(raise|return|yield(?:return)?)(?=\\s)(\\s+((\\[).+(])))?'
'beginCaptures':
'1':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'name': ''
'2':
'name': 'comment.line.keyword.yard.ruby'
'name': 'punctuation.definition.comment.ruby'
'3':
'name': 'comment.line.yard.ruby'
'name': ''
'4':
'name': 'comment.line.type.yard.ruby'
'name': 'comment.line.keyword.punctuation.yard.ruby'
'5':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.keyword.yard.ruby'
'6':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.yard.ruby'
'7':
'name': 'comment.line.string.yard.ruby'
'name': 'comment.line.type.yard.ruby'
'8':
'name': 'comment.line.punctuation.yard.ruby'
'9':
'name': 'comment.line.punctuation.yard.ruby'
'end': '^(?!\\s*#\\3\\s{2,})'
'contentName': 'comment.line.string.yard.ruby'
'name': 'comment.line.number-sign.ruby'
'patterns': [
{
'include': '#yard'
}
{
'include': '#yard_continuation'
}
]
'yard_directive':
'comment': 'For YARD directives'
'match': '(@!)(attribute|endgroup|group|macro|method|parse|scope|visibility)(\\s+((\\[).+(])))?(?=\\s)(.*)$'
'captures':
'begin': '^(\\s*)(#)(\\s*)(@!)(attribute|endgroup|group|macro|method|parse|scope|visibility)(\\s+((\\[).+(])))?(?=\\s)'
'beginCaptures':
'1':
'name': 'comment.line.keyword.punctuation.yard.ruby'
'name': ''
'2':
'name': 'comment.line.keyword.yard.ruby'
'name': 'punctuation.definition.comment.ruby'
'3':
'name': 'comment.line.yard.ruby'
'name': ''
'4':
'name': 'comment.line.type.yard.ruby'
'name': 'comment.line.keyword.punctuation.yard.ruby'
'5':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.keyword.yard.ruby'
'6':
'name': 'comment.line.punctuation.yard.ruby'
'name': 'comment.line.yard.ruby'
'7':
'name': 'comment.line.string.yard.ruby'
'name': 'comment.line.type.yard.ruby'
'8':
'name': 'comment.line.punctuation.yard.ruby'
'9':
'name': 'comment.line.punctuation.yard.ruby'
'end': '^(?!\\s*#\\3\\s{2,})'
'contentName': 'comment.line.string.yard.ruby'
'name': 'comment.line.number-sign.ruby'
'patterns': [
{
'include': '#yard'
}
{
'include': '#yard_continuation'
}
]
'yard_continuation':
'match': '^\\s*#'
'name': 'punctuation.definition.comment.ruby'
96 changes: 58 additions & 38 deletions spec/ruby-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -587,36 +587,51 @@ describe "TextMate Ruby grammar", ->
expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[3]).toEqual value: 'private', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']

{tokens} = grammar.tokenizeLine('# @deprecated Because I said so')
expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[3]).toEqual value: 'deprecated', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[4]).toEqual value: ' Because I said so', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
tokens = grammar.tokenizeLines '''
# @deprecated Because I said so,
# end of discussion
'''
expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[0][3]).toEqual value: 'deprecated', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[0][4]).toEqual value: ' Because I said so,', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1][1]).toEqual value: ' end of discussion', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']

{tokens} = grammar.tokenizeLine('# @raise [Bar] Baz')
expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[3]).toEqual value: 'raise', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[6]).toEqual value: 'Bar', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[8]).toEqual value: ' Baz', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
tokens = grammar.tokenizeLines '''
# @raise [AccountBalanceError] if the account does not have
# sufficient funds to perform the transaction
'''
expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[0][3]).toEqual value: 'raise', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[0][5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][6]).toEqual value: 'AccountBalanceError', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[0][7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][8]).toEqual value: ' if the account does not have', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1][1]).toEqual value: ' sufficient funds to perform the transaction', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']

{tokens} = grammar.tokenizeLine('# @param foo [Bar] Baz')
expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[3]).toEqual value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[5]).toEqual value: 'foo', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.parameter.yard.ruby']
expect(tokens[6]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[7]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[8]).toEqual value: 'Bar', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[9]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[10]).toEqual value: ' Baz', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
tokens = grammar.tokenizeLines '''
# @param value [Object] describe value param in a long way which
# makes it multiline
'''
expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[0][3]).toEqual value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[0][5]).toEqual value: 'value', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.parameter.yard.ruby']
expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[0][7]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][8]).toEqual value: 'Object', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[0][9]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][10]).toEqual value: ' describe value param in a long way which', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1][1]).toEqual value: ' makes it multiline', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']

{tokens} = grammar.tokenizeLine('# @param [Bar] Baz')
expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
Expand Down Expand Up @@ -651,16 +666,21 @@ describe "TextMate Ruby grammar", ->
expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[8]).toEqual value: ' comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']

{tokens} = grammar.tokenizeLine('# @!attribute [r] foo comment')
expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[2]).toEqual value: '@!', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[3]).toEqual value: 'attribute', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[6]).toEqual value: 'r', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[8]).toEqual value: ' foo comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
tokens = grammar.tokenizeLines '''
# @!attribute [r] count the number of items
# present in the list
'''
expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby']
expect(tokens[0][2]).toEqual value: '@!', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby']
expect(tokens[0][3]).toEqual value: 'attribute', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby']
expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby']
expect(tokens[0][5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][6]).toEqual value: 'r', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby']
expect(tokens[0][7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby']
expect(tokens[0][8]).toEqual value: ' count the number of items', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']
expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby']
expect(tokens[1][1]).toEqual value: ' present in the list', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby']

it "tokenizes a method with *args properly", ->
{tokens} = grammar.tokenizeLine('def method(*args)')
Expand Down

0 comments on commit dd2de8e

Please sign in to comment.