Class: Solargraph::SourceMap::Mapper

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/source_map/mapper.rb

Overview

The Mapper generates pins and other data for SourceMaps.

This class is used internally by the SourceMap class. Users should not normally need to call it directly.

Constant Summary collapse

DIRECTIVE_REGEXP =
/(@!method|@!attribute|@!visibility|@!domain|@!macro|@!parse|@!override)/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.map(source) ⇒ Array

Parameters:

Returns:

  • (Array)


51
52
53
54
55
# File 'lib/solargraph/source_map/mapper.rb', line 51

def map source
  # @sg-ignore Need to add nil check here
  return new.unmap(source.filename, source.code) unless source.parsed?
  new.map source
end

Instance Method Details

#find_directive_line_number(comment, tag, start) ⇒ Integer

Parameters:

  • comment (String)
  • tag (String)
  • start (Integer)

Returns:

  • (Integer)


86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/solargraph/source_map/mapper.rb', line 86

def find_directive_line_number comment, tag, start
  # Avoid overruning the index
  return start unless start < comment.lines.length
  # @sg-ignore Need to add nil check here
  num = comment.lines[start..].find_index do |line|
    # Legacy method directives might be `@method` instead of `@!method`
    # @todo Legacy syntax should probably emit a warning
    line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
  end
  # @sg-ignore Need to add nil check here
  num.to_i + start
end

#map(source) ⇒ Array

Generate the data.

Parameters:

Returns:

  • (Array)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/solargraph/source_map/mapper.rb', line 21

def map source
  @source = source
  @filename = source.filename
  @code = source.code
  @comments = source.comments
  @pins, @locals = Parser.map(source)
  # @param p [Solargraph::Pin::Base]
  @pins.each { |p| p.source = :code }
  @locals.each { |l| l.source = :code }
  process_comment_directives
  [@pins, @locals]
  # rescue Exception => e
  #   Solargraph.logger.warn "Error mapping #{source.filename}: [#{e.class}] #{e.message}"
  #   Solargraph.logger.warn e.backtrace.join("\n")
  #   [[], []]
end

#pinsArray<Solargraph::Pin::Base>

Returns:



59
60
61
62
# File 'lib/solargraph/source_map/mapper.rb', line 59

def pins
  # @type [Array<Solargraph::Pin::Base>]
  @pins ||= []
end

#process_comment(source_position, comment_position, comment) ⇒ void

This method returns an undefined value.

Parameters:



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/solargraph/source_map/mapper.rb', line 68

def process_comment source_position, comment_position, comment
  return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
  cmnt = remove_inline_comment_hashes(comment)
  parse = Solargraph::Source.parse_docstring(cmnt)
  last_line = 0
  # @param d [YARD::Tags::Directive]
  parse.directives.each do |d|
    line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
    pos = Solargraph::Position.new(comment_position.line + line_num - 1, comment_position.column)
    process_directive(source_position, pos, d)
    last_line = line_num + 1
  end
end

#process_comment_directivesvoid

This method returns an undefined value.



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/solargraph/source_map/mapper.rb', line 135

def process_comment_directives
  return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
  code_lines = @code.lines
  @source.associated_comments.each do |line, comments|
    src_pos = if line
                Position.new(line,
                             code_lines[line].to_s.chomp.index(/[^\s]/) || 0)
              else
                Position.new(
                  code_lines.length, 0
                )
              end
    # @sg-ignore Need to add nil check here
    com_pos = Position.new(line + 1 - comments.lines.length, 0)
    process_comment(src_pos, com_pos, comments)
  end
rescue StandardError => e
  raise e.class, "Error processing comment directives in #{@filename}: #{e.message}"
end

#process_directive(source_position, comment_position, directive) ⇒ void

This method returns an undefined value.

Parameters:

  • source_position (Position)
  • comment_position (Position)
  • directive (YARD::Tags::Directive)


103
104
105
106
107
108
109
110
# File 'lib/solargraph/source_map/mapper.rb', line 103

def process_directive source_position, comment_position, directive
  directive_processor = YardMap::Directives.for(directive)
  return unless directive_processor

  @pins += directive_processor.process_directive(
    @source, @pins, source_position, comment_position, directive
  )
end

#remove_inline_comment_hashes(comment) ⇒ String

Parameters:

  • comment (String)

Returns:

  • (String)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/solargraph/source_map/mapper.rb', line 114

def remove_inline_comment_hashes comment
  ctxt = ''
  num = nil
  started = false
  comment.lines.each do |l|
    # Trim the comment and minimum leading whitespace
    p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
    if num.nil? && !p.strip.empty?
      num = p.index(/[^ ]/)
      started = true
    elsif started && !p.strip.empty?
      cur = p.index(/[^ ]/)
      # @sg-ignore Need to add nil check here
      num = cur if cur < num
    end
    ctxt += p[num..].to_s if started
  end
  ctxt
end

#unmap(filename, code) ⇒ Array

Parameters:

  • filename (String)
  • code (String)

Returns:

  • (Array)


41
42
43
44
45
46
# File 'lib/solargraph/source_map/mapper.rb', line 41

def unmap filename, code
  s = Position.new(0, 0)
  e = Position.from_offset(code, code.length)
  location = Location.new(filename, Range.new(s, e))
  [[Pin::Namespace.new(location: location, name: '', source: :source_map)], []]
end