Class: Steep::Locator::Inline

Inherits:
Object
  • Object
show all
Defined in:
lib/steep/locator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ Inline

Returns a new instance of Inline.



163
164
165
# File 'lib/steep/locator.rb', line 163

def initialize(source)
  @source = source
end

Instance Attribute Details

#sourceObject (readonly)

Returns the value of attribute source.



161
162
163
# File 'lib/steep/locator.rb', line 161

def source
  @source
end

Instance Method Details

#find(line, column) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
# File 'lib/steep/locator.rb', line 167

def find(line, column)
  position = source.buffer.loc_to_pos([line, column])

  source.declarations.each do |decl|
    if ast = find0(position, decl)
      return inline_result(position, ast)
    end
  end

  nil
end

#find0(position, ast) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/steep/locator.rb', line 179

def find0(position, ast)
  case ast
  when RBS::AST::Ruby::Declarations::ClassDecl
    if ast.location.start_pos <= position && position <= ast.location.end_pos
      # Check if position is within super class
      if ast.super_class
        if ast.super_class.location.start_pos <= position && position <= ast.super_class.location.end_pos
          # Check if position is on type arguments
          if ast.super_class.type_annotation
            if ast.super_class.type_annotation.location.start_pos <= position && position <= ast.super_class.type_annotation.location.end_pos
              return InlineAnnotationResult.new(ast.super_class.type_annotation, ast)
            end
          end
        end
      end

      ast.members.each do |member|
        if sub = find0(position, member)
          return sub
        end
      end
    end
  when RBS::AST::Ruby::Declarations::ModuleDecl
    if ast.location.start_pos <= position && position <= ast.location.end_pos
      ast.members.each do |member|
        if sub = find0(position, member)
          return sub
        end
      end
    end
  when RBS::AST::Ruby::Members::DefMember
    case annotations = ast.method_type.type_annotations
    when RBS::AST::Ruby::Members::MethodTypeAnnotation::DocStyle
      if annotation = annotations.return_type_annotation
        if annotation.location.start_pos <= position && position <= annotation.location.end_pos
          return InlineAnnotationResult.new(annotations.return_type_annotation, ast)
        end
      end
    when Array
      annotations.each do |annotation|
        case annotation
        when RBS::AST::Ruby::Annotations::ColonMethodTypeAnnotation
          if annotation.location.start_pos <= position && position <= annotation.location.end_pos
            return InlineAnnotationResult.new(annotation, ast)
          end
        when RBS::AST::Ruby::Annotations::MethodTypesAnnotation
          if annotation.location.start_pos <= position && position <= annotation.location.end_pos
            return InlineAnnotationResult.new(annotation, ast)
          end
        end
      end
    end
  when RBS::AST::Ruby::Members::IncludeMember, RBS::AST::Ruby::Members::ExtendMember, RBS::AST::Ruby::Members::PrependMember
    if ast.annotation.is_a?(RBS::AST::Ruby::Annotations::TypeApplicationAnnotation)
      if ast.annotation.location.start_pos <= position && position <= ast.annotation.location.end_pos
        return InlineAnnotationResult.new(ast.annotation, ast)
      end
    end
  when RBS::AST::Ruby::Members::AttrReaderMember, RBS::AST::Ruby::Members::AttrWriterMember, RBS::AST::Ruby::Members::AttrAccessorMember
    if annotation = ast.type_annotation
      if annotation.location.start_pos <= position && position <= annotation.location.end_pos
        return InlineAnnotationResult.new(annotation, ast)
      end
    end
  when RBS::AST::Ruby::Members::InstanceVariableMember
    annotation = ast.annotation
    if annotation.location.start_pos <= position && position <= annotation.location.end_pos
      return InlineAnnotationResult.new(annotation, ast)
    end
  when RBS::AST::Ruby::Declarations::ConstantDecl
    if annotation = ast.type_annotation
      if annotation.location.start_pos <= position && position <= annotation.location.end_pos
        return InlineAnnotationResult.new(annotation, ast)
      end
    end
  when RBS::AST::Ruby::Declarations::ClassModuleAliasDecl
    if annotation = ast.annotation
      if annotation.location.start_pos <= position && position <= annotation.location.end_pos
        return InlineAnnotationResult.new(annotation, ast)
      end
    end
  end

  nil
end

#inline_result(position, result) ⇒ Object



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/steep/locator.rb', line 265

def inline_result(position, result)
  type_result = nil #: InlineTypeResult?

  case result.annotation
  when RBS::AST::Ruby::Annotations::ReturnTypeAnnotation
    if type_location = result.annotation.return_type.location
      if type_location.start_pos <= position && position <= type_location.end_pos
        type_result = InlineTypeResult.new(result.annotation.return_type, result)
      end
    end
  when RBS::AST::Ruby::Annotations::ColonMethodTypeAnnotation
    type = result.annotation.method_type.each_type.find do |type|
      if type_location = type.location
        type_location.start_pos <= position && position <= type_location.end_pos
      end
    end

    if type
      type_result = InlineTypeResult.new(type, result)
    end
  when RBS::AST::Ruby::Annotations::MethodTypesAnnotation
    overload = result.annotation.overloads.find do
      if location = _1.method_type.location
        location.start_pos <= position && position <= location.end_pos
      end
    end

    if overload
      type = overload.method_type.each_type.find do |type|
        if type_location = type.location
          type_location.start_pos <= position && position <= type_location.end_pos
        end
      end

      if type
        type_result = InlineTypeResult.new(type, result)
      end
    end
  when RBS::AST::Ruby::Annotations::TypeApplicationAnnotation
    # Find type argument that contains the position
    type = result.annotation.type_args.find do |type_arg|
      if type_location = type_arg.location
        type_location.start_pos <= position && position <= type_location.end_pos
      end
    end

    if type
      type_result = InlineTypeResult.new(type, result)
    end
  when RBS::AST::Ruby::Annotations::NodeTypeAssertion
    # Handle type annotations for attr_reader/writer/accessor
    if type_location = result.annotation.type.location
      if type_location.start_pos <= position && position <= type_location.end_pos
        type_result = InlineTypeResult.new(result.annotation.type, result)
      end
    end
  when RBS::AST::Ruby::Annotations::InstanceVariableAnnotation
    # Handle type annotations for instance variables
    if type_location = result.annotation.type.location
      if type_location.start_pos <= position && position <= type_location.end_pos
        type_result = InlineTypeResult.new(result.annotation.type, result)
      end
    end
  when RBS::AST::Ruby::Annotations::ClassAliasAnnotation, RBS::AST::Ruby::Annotations::ModuleAliasAnnotation
    # Handle class-alias and module-alias annotations with explicit type names
    if result.annotation.type_name && result.annotation.type_name_location
      if result.annotation.type_name_location.start_pos <= position && position <= result.annotation.type_name_location.end_pos
        return InlineTypeNameResult.new(
          result.annotation.type_name,
          result.annotation.type_name_location,
          result
        )
      end
    end
  end

  if type_result
    type_name_result(position, type_result)
  else
    result
  end
end

#type_name_result(position, result) ⇒ Object



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/steep/locator.rb', line 348

def type_name_result(position, result)
  locator = RBS::Locator.new(buffer: source.buffer, decls: [], dirs: [])
  components = [] #: Array[RBS::Locator::component]

  if locator.find_in_type(position, type: result.type, array: components)
    symbol, type, * = components
    if symbol.is_a?(Symbol)
      type_name = nil #: RBS::TypeName?
      location = nil #: RBS::Location?

      case type
      when RBS::Types::ClassInstance, RBS::Types::ClassSingleton, RBS::Types::Alias, RBS::Types::Interface
        if symbol == :name
          type_loc = type.location or raise
          type_name = type.name
          location = type_loc[:name] or raise
        end
      end

      if type_name && location
        return InlineTypeNameResult.new(type_name, location, result)
      end
    end
  end

  result
end