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

Added scopes for many kernel and special methods in tree-sitter parser #285

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions grammars/tree-sitter-ruby.cson
Original file line number Diff line number Diff line change
Expand Up @@ -130,25 +130,18 @@ scopes:
'interpolation > "}"': 'punctuation.section.embedded'

'constant': [
{exact: 'ENV', scopes: 'support.variable'}
{match: '^[A-Z_0-9]+$', scopes: 'variable.constant'}
'entity.name.type.class'
]
'global_variable': 'variable.other.readwrite.global'
'superclass > constant': 'entity.other.inherited-class'

'identifier': [
{
match: '^__(FILE|LINE|ENCODING)__$',
scopes: 'support.variable'
}
{
match: '^(public|protected|private)$'
scopes: 'keyword.other.special-method'
}
{
match: '^(block_given\?|iterator\?|alias_method)'
scopes: 'keyword.control'
}
{match: '^__(FILE|LINE|ENCODING)__$', scopes: 'support.variable'}
{match: '^(caller|binding|__dir__)$', scopes: 'support.function.kernel'}
{match: '^(public|protected|private|module_function|raise|caller|binding)$', scopes: 'keyword.other.special-method'}
{match: '^(block_given\?|iterator\?|alias_method)', scopes: 'keyword.control'}
]

'escape_sequence': 'constant.character.escape'
Expand All @@ -165,15 +158,22 @@ scopes:

'singleton_method > identifier:nth-child(3)': 'entity.name.function'
'setter > identifier': 'entity.name.function'
'call > identifier:nth-child(2)': 'entity.name.function'
'call > identifier:nth-child(2)': [
{exact: 'new', scopes: 'keyword.other.special-method'}
'entity.name.function'
]
'method_call > identifier:nth-child(0)': [
{exact: 'require', scopes: 'support.function'}
{match: '^(public|protected|private)$', scopes: 'keyword.other.special-method'}
# Gemile specific TODO: move to separate grammar?
{match: '^(gem|git|group|platforms|ruby|source|eval_gemfile)$', scopes: 'keyword.other.special-method'}

{match: '^(require|require_relative|loop|eval|lambda|catch|raise|exit|throw|autoload|puts)$', scopes: 'support.function.kernel'}
{match: '^(public|protected|private|module_function|new|include|extend|inspect)$', scopes: 'keyword.other.special-method'}
{match: '^(attr_accessor|attr_reader|attr_writer)$', scopes: 'keyword.other.special-method'}
{match: '^(block_given\?|iterator\?|alias_method)', scopes: 'keyword.control'}
'entity.name.function'
]

'block_parameters > identifier': 'variable.other.block'
'block_parameters > identifier, lambda_parameters > identifier': 'variable.other.block'
'method_parameters > identifier, optional_parameter > identifier': 'variable.parameter.function'
'keyword_parameter > identifier:nth-child(0)': 'constant.other.symbol'
'class_variable': 'variable.other.object.property'
Expand Down Expand Up @@ -254,3 +254,5 @@ scopes:
'nil': 'constant.language.nil'
'true': 'constant.language.true'
'false': 'constant.language.false'

'lambda > "->"': 'support.function.kernel'
65 changes: 65 additions & 0 deletions spec/tree-sitter-gemfile-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const dedent = require('dedent')

describe('Tree-sitter Gemfile grammar', () => {
beforeEach(async () => {
atom.config.set('core.useTreeSitterParsers', true)
await atom.packages.activatePackage('language-ruby')
})

it('tokenizes ruby code', async () => {
const editor = await atom.workspace.open('Gemfile')

editor.setText(dedent`
:foo
%i(foo)
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .constant.other.symbol'
)

expect(editor.scopeDescriptorForBufferPosition([1, 3]).toString()).toBe(
'.source.ruby .constant.other.symbol'
)
})

it('tokenizes Gemfile specific code', async () => {
const editor = await atom.workspace.open('Gemfile')

editor.setText(dedent`
source 'https://rubygems.org'
ruby '2.5.1'
gem 'rails', '~> 5.2', '< 6.0'

group :development, :test do
gem 'pry'
end

eval_gemfile 'Gemfile.local'
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([1, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([2, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([4, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([5, 3]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([8, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
})
})
150 changes: 149 additions & 1 deletion spec/tree-sitter-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,95 @@ describe('Tree-sitter Ruby grammar', () => {
)
})

it('tokenizes constants', async () => {
const editor = await atom.workspace.open('foo.rb')

editor.setText(dedent`
HELLO = __FILE__.dirname
ClassName::HELLO
ENV["ABC"]
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .variable.constant'
)

expect(editor.scopeDescriptorForBufferPosition([0, 10]).toString()).toBe(
'.source.ruby .support.variable'
)

expect(editor.scopeDescriptorForBufferPosition([1, 12]).toString()).toBe(
'.source.ruby .variable.constant'
)

expect(editor.scopeDescriptorForBufferPosition([2, 1]).toString()).toBe(
'.source.ruby .support.variable'
)
})


it('tokenizes kernel methods', async () => {
const editor = await atom.workspace.open('foo.rb')
editor.setText(dedent`
require 'hello'
require_relative '.world'

catch :hello do
throw :hello
end

raise StandardError
binding.pry
caller
puts 'asfd'
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([1, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([3, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([4, 3]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([7, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([8, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([8, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([9, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)
})

it('tokenizes visibility modifiers', async () => {
const editor = await atom.workspace.open('foo.rb')

editor.setText(dedent`
public
protected
private
module_function

public def foo; end
protected def bar; end
private def baz; end
module_function def quux; end
`)

expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe(
Expand All @@ -45,7 +123,7 @@ describe('Tree-sitter Ruby grammar', () => {
expect(editor.scopeDescriptorForBufferPosition([2, 0]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
expect(editor.scopeDescriptorForBufferPosition([4, 0]).toString()).toBe(
expect(editor.scopeDescriptorForBufferPosition([3, 0]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
expect(editor.scopeDescriptorForBufferPosition([5, 0]).toString()).toBe(
Expand All @@ -54,6 +132,12 @@ describe('Tree-sitter Ruby grammar', () => {
expect(editor.scopeDescriptorForBufferPosition([6, 0]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
expect(editor.scopeDescriptorForBufferPosition([7, 0]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
expect(editor.scopeDescriptorForBufferPosition([8, 0]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
})

it('tokenizes keyword predicates', async () => {
Expand Down Expand Up @@ -130,4 +214,68 @@ describe('Tree-sitter Ruby grammar', () => {
'.source.ruby .variable'
)
})

it('tokenizes lambdas', async () => {
const editor = await atom.workspace.open('foo.rb')
editor.setText(dedent`
foo 'bar', ->(hello) { puts hello }

lambda { |hello|
puts hello
}
`)

expect(editor.scopeDescriptorForBufferPosition([0, 12]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([0, 15]).toString()).toBe(
'.source.ruby .variable.other.block'
)

expect(editor.scopeDescriptorForBufferPosition([2, 1]).toString()).toBe(
'.source.ruby .support.function.kernel'
)

expect(editor.scopeDescriptorForBufferPosition([2, 11]).toString()).toBe(
'.source.ruby .variable.other.block'
)
})

it('tokenizes special methods', async () => {
const editor = await atom.workspace.open('foo.rb')
editor.setText(dedent`
include HelloWorld
extend FooBar
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([1, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
})

it('tokenizes attr accessors', async () => {
const editor = await atom.workspace.open('foo.rb')
editor.setText(dedent`
attr_accessor :hello
attr_reader :foo
attr_writer :bar
`)

expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([1, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)

expect(editor.scopeDescriptorForBufferPosition([2, 1]).toString()).toBe(
'.source.ruby .keyword.other.special-method'
)
})
})