Class: Solargraph::Source

Inherits:
Object
  • Object
show all
Includes:
EncodingFixes, NodeMethods
Defined in:
lib/solargraph/source.rb,
lib/solargraph/source/chain.rb,
lib/solargraph/source/change.rb,
lib/solargraph/source/cursor.rb,
lib/solargraph/source/updater.rb,
lib/solargraph/source/chain/call.rb,
lib/solargraph/source/chain/head.rb,
lib/solargraph/source/chain/link.rb,
lib/solargraph/source/node_chainer.rb,
lib/solargraph/source/node_methods.rb,
lib/solargraph/source/chain/literal.rb,
lib/solargraph/source/chain/constant.rb,
lib/solargraph/source/chain/variable.rb,
lib/solargraph/source/encoding_fixes.rb,
lib/solargraph/source/flawed_builder.rb,
lib/solargraph/source/source_chainer.rb,
lib/solargraph/source/chain/class_variable.rb,
lib/solargraph/source/chain/global_variable.rb,
lib/solargraph/source/chain/instance_variable.rb

Overview

A Ruby file that has been parsed into an AST.

Defined Under Namespace

Modules: EncodingFixes, NodeMethods Classes: Chain, Change, Cursor, NodeChainer, SourceChainer, Updater

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NodeMethods

const_from, drill_signature, get_node_end_position, get_node_start_position, infer_literal_node_type, pack_name, resolve_node_signature, unpack_name

Methods included from EncodingFixes

normalize

Constructor Details

#initialize(code, filename = nil, version = 0) ⇒ Source

Returns a new instance of Source.

Parameters:

  • code (String)
  • filename (String) (defaults to: nil)
  • version (Integer) (defaults to: 0)


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/solargraph/source.rb', line 39

def initialize code, filename = nil, version = 0
  @code = normalize(code)
  @repaired = code
  @filename = filename
  @version = version
  @domains = []
  begin
    @node, @comments = Source.parse_with_comments(@code, filename)
    @parsed = true
  rescue Parser::SyntaxError, EncodingError => e
    @node, @comments = Source.parse_with_comments(@code.gsub(/[^s]/, ' '), filename)
    @parsed = false
  rescue Exception => e
    STDERR.puts e.message
    STDERR.puts e.backtrace
    raise "Error parsing #{filename || '(source)'}: [#{e.class}] #{e.message}"
  ensure
    @code.freeze
  end
end

Instance Attribute Details

#codeString

Returns:

  • (String)


22
23
24
# File 'lib/solargraph/source.rb', line 22

def code
  @code
end

#commentsObject (readonly)

Returns the value of attribute comments.



27
28
29
# File 'lib/solargraph/source.rb', line 27

def comments
  @comments
end

#filenameString (readonly)

Returns:

  • (String)


30
31
32
# File 'lib/solargraph/source.rb', line 30

def filename
  @filename
end

#nodeParser::AST::Node (readonly)

Returns:

  • (Parser::AST::Node)


25
26
27
# File 'lib/solargraph/source.rb', line 25

def node
  @node
end

#versionInteger

TODO:

Deprecate?

Returns:

  • (Integer)


34
35
36
# File 'lib/solargraph/source.rb', line 34

def version
  @version
end

Class Method Details

.load(filename) ⇒ Solargraph::Source

Parameters:

  • filename (String)

Returns:



241
242
243
244
245
246
# File 'lib/solargraph/source.rb', line 241

def load filename
  file = File.open(filename, 'rb')
  code = file.read
  file.close
  Source.load_string(code, filename)
end

.load_string(code, filename = nil, version = 0) ⇒ Solargraph::Source

Parameters:

  • code (String)
  • filename (String) (defaults to: nil)

Returns:



251
252
253
# File 'lib/solargraph/source.rb', line 251

def load_string code, filename = nil, version = 0
  Source.new code, filename, version
end

.parse(code, filename = nil) ⇒ Object



261
262
263
264
265
# File 'lib/solargraph/source.rb', line 261

def parse code, filename = nil
  buffer = Parser::Source::Buffer.new(filename, 0)
  buffer.source = code.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '_')
  parser.parse(buffer)
end

.parse_with_comments(code, filename = nil) ⇒ Object



255
256
257
258
259
# File 'lib/solargraph/source.rb', line 255

def parse_with_comments code, filename = nil
  buffer = Parser::Source::Buffer.new(filename, 0)
  buffer.source = code.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '_')
  parser.parse_with_comments(buffer)
end

Instance Method Details

#at(range) ⇒ Object

Parameters:



61
62
63
# File 'lib/solargraph/source.rb', line 61

def at range
  from_to range.start.line, range.start.character, range.ending.line, range.ending.character
end

#comment_at?(position) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


144
145
146
147
148
149
150
# File 'lib/solargraph/source.rb', line 144

def comment_at? position
  comment_ranges.each do |range|
    return true if range.include?(position)
    break if range.ending.line > position.line
  end
  false
end

#cursor_at(position) ⇒ Source::Cursor

Parameters:

Returns:



119
120
121
# File 'lib/solargraph/source.rb', line 119

def cursor_at position
  Cursor.new(self, position)
end

#error_rangesArray<Range>

Returns:



170
171
172
# File 'lib/solargraph/source.rb', line 170

def error_ranges
  @error_ranges ||= []
end

#from_to(l1, c1, l2, c2) ⇒ Object



65
66
67
68
69
# File 'lib/solargraph/source.rb', line 65

def from_to l1, c1, l2, c2
  b = Solargraph::Position.line_char_to_offset(@code, l1, c1)
  e = Solargraph::Position.line_char_to_offset(@code, l2, c2)
  @code[b..e-1]
end

#node_at(line, column) ⇒ AST::Node

Get the nearest node that contains the specified index.

Parameters:

  • line (Integer)
  • column (Integer)

Returns:

  • (AST::Node)


76
77
78
# File 'lib/solargraph/source.rb', line 76

def node_at(line, column)
  tree_at(line, column).first
end

#parsed?Boolean

Returns:

  • (Boolean)


124
125
126
# File 'lib/solargraph/source.rb', line 124

def parsed?
  @parsed
end

#references(name) ⇒ Array<Location>

Parameters:

  • name (String)

Returns:



154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/solargraph/source.rb', line 154

def references name
  inner_node_references(name, node).map do |n|
    offset = Position.to_offset(code, get_node_start_position(n))
    soff = code.index(name, offset)
    eoff = soff + name.length
    Location.new(
      filename,
      Range.new(
        Position.from_offset(code, soff),
        Position.from_offset(code, eoff)
      )
    )
  end
end

#repaired?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/solargraph/source.rb', line 128

def repaired?
  @is_repaired ||= (@code != @repaired)
end

#string_at?(position) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


134
135
136
137
138
139
140
# File 'lib/solargraph/source.rb', line 134

def string_at? position
  string_ranges.each do |range|
    return true if range.include?(position)
    break if range.ending.line > position.line
  end
  false
end

#synchronize(updater) ⇒ Source

Parameters:

Returns:



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/solargraph/source.rb', line 97

def synchronize updater
  raise 'Invalid synchronization' unless updater.filename == filename
  real_code = updater.write(@code)
  if real_code == @code
    @version = updater.version
    return self
  end
  synced = Source.new(real_code, filename)
  if synced.parsed?
    synced.version = updater.version
    return synced
  end
  incr_code = updater.repair(@repaired)
  synced = Source.new(incr_code, filename)
  synced.error_ranges.concat (error_ranges + updater.changes.map(&:range))
  synced.code = real_code
  synced.version = updater.version
  synced
end

#tree_at(line, column) ⇒ Array<AST::Node>

Get an array of nodes containing the specified index, starting with the nearest node and ending with the root.

Parameters:

  • line (Integer)
  • column (Integer)

Returns:

  • (Array<AST::Node>)


86
87
88
89
90
91
92
# File 'lib/solargraph/source.rb', line 86

def tree_at(line, column)
  # offset = Position.line_char_to_offset(@code, line, column)
  position = Position.new(line, column)
  stack = []
  inner_tree_at @node, position, stack
  stack
end