-
Notifications
You must be signed in to change notification settings - Fork 31
/
whitequark_parser_init.rb
127 lines (106 loc) · 3.67 KB
/
whitequark_parser_init.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#
# SonarSource SLang
# Copyright (C) 2018-2019 SonarSource SA
# mailto:info AT sonarsource DOT com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
require 'parser/ruby33'
require 'java'
# Custom builder in order to avoid throwing an error when literals contain an escape sequences incompatible with UTF-8
# See https://github.com/whitequark/parser/issues/283
# Inspired from https://github.com/eapache/starscope/pull/166
class Builder < Parser::Builders::Default
# opt-in to most recent AST format (used for Backwards compatibility when breaking changes are introduced in AST format)
# In order not to break backward compatibility, when breaking changes are introduced in a newer version of the parser AST, these new
# features have to be manually enabled. Here we enable the latest/current features at time of development.
@emit_lambda = true
@emit_procarg0 = true
@emit_encoding = true
@emit_index = true
def string_value(token)
value(token)
end
end
# In order to retrieve AST, comments, and tokens, we need to use the 'tokenize' method of the ruby Parser object.
# However, the 'tokenize' method takes directly a Buffer object as parameter. Here, we map the string content to the Buffer object the
# same way it is done in the 'Parser::Base.parse' and 'Parser::Base.setup_source_buffer' methods.
def parse_with_tokens(content, filename)
parser = Parser::Ruby33.new(Builder.new)
parser.diagnostics.all_errors_are_fatal = true
parser.diagnostics.ignore_warnings = true
content = content.dup.force_encoding(parser.default_encoding)
source_buffer = Parser::Source::Buffer.new(filename, 1)
source_buffer.source = content
parser.tokenize(source_buffer)
end
def visit(ast, visitor)
processor = ProcessorBridge.new(visitor)
processor.process(ast)
end
# Bridge between RubyVisitor and Parser::AST::Processor APIs
class ProcessorBridge < Parser::AST::Processor
def initialize(visitor)
@visitor = visitor
end
def process(node)
return if node.nil?
@visitor.beforeVisit(AstNode.new(node))
node = super
astNode = AstNode.new(node)
tree = @visitor.visitNode(astNode, java.util.ArrayList.new(node.to_a))
@visitor.afterVisit(astNode)
tree
end
end
# Bridge between Parser::AST::Node and AstNode
class AstNode
include org.sonarsource.ruby.converter.AstNode
def initialize(node)
@node = node
end
def type
if @node.respond_to?(:type)
@node.type
else
@node.to_s
end
end
def asString
@node.to_s
end
def source
@node.location.expression.source
end
def textRange()
textRangeForAttribute('expression')
end
def textRangeForAttribute(attr)
if @node.location.respond_to?(attr)
loc = @node.location.public_send(attr)
return if loc.nil?
textRangeFromLocation(loc)
end
end
def textRangeFromLocation(loc)
org.sonarsource.slang.impl.TextRangeImpl.new(loc.line, loc.column, loc.last_line, loc.last_column)
end
def node
@node
end
def availableAttributes
node.location.instance_variables
end
end