0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SteepコードリーディングAdvent Calendar 2024

Day 6

Steepコードリーディング(6日目)

Posted at

Steepコードリーディング(6日目)

今回は以下のJobが何をしているのかざっくりと追い、目的の型検査のJobを見つける。

  • StartTypeCheckJob
  • ValidateAppSignatureJob
  • ValidateLibrarySignatureJob
  • TypeCheckCodeJob
  • WorkspaceSymbolJob
  • StatsJob
  • GotoJob

と意気込んでいたが、Job自体は単なるStructオブジェクトに過ぎなかった。

WorkspaceSymbolJob = _ = Struct.new(:query, :id, keyword_init: true)
StatsJob = _ = Struct.new(:id, keyword_init: true)
StartTypeCheckJob = _ = Struct.new(:guid, :changes, keyword_init: true)
TypeCheckCodeJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
ValidateAppSignatureJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
ValidateLibrarySignatureJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
class GotoJob < Struct.new(:id, :kind, :params, keyword_init: true)
  def self.implementation(id:, params:)
    new(
      kind: :implementation,
      id: id,
      params: params
    )
  end

  def self.definition(id:, params:)
    new(
      kind: :definition,
      id: id,
      params: params
    )
  end

  def self.type_definition(id:, params:)
    new(
      kind: :type_definition,
      id: id,
      params: params
    )
  end

  def implementation?
    kind == :implementation
  end

  def definition?
    kind == :definition
  end

  def type_definition?
    kind == :type_definition
  end
end

仕方ないのでhandle_jobでの処理内容からいくつかあたりをつけて追っていくことにする。

StartTypeCheckJob

ログを吐いてservice.updateを行っている。

when StartTypeCheckJob
  Steep.logger.info { "Processing StartTypeCheckJob for guid=#{job.guid}" }
  service.update(changes: job.changes)

serviceメソッドの中身はこれ。

def service
  @service ||= Services::TypeCheckService.new(project: project)
end

ん?なんか早くもゴールを見つけた気がする...?

ValidateAppSignatureJob

service.validate_signatureを行っている。メソッド名から察するにRBSのSyntaxチェックとかだろうか。

when ValidateAppSignatureJob
  if job.guid == current_type_check_guid
    Steep.logger.info { "Processing ValidateAppSignature for guid=#{job.guid}, path=#{job.path}" }

    formatter = Diagnostic::LSPFormatter.new({}, **{})

    diagnostics = service.validate_signature(path: project.relative_path(job.path), target: job.target)

    typecheck_progress(
      path: job.path,
      guid: job.guid,
      target: job.target,
      diagnostics: diagnostics.filter_map { formatter.format(_1) }
    )
  end

typecheck_progressはこれ。

def typecheck_progress(guid:, path:, target:, diagnostics:)
  writer.write(CustomMethods::TypeCheck__Progress.notification({ guid: guid, path: path.to_s, target: target.name.to_s, diagnostics: diagnostics }))
end

ValidateLibrarySignatureJob

これもservice.validate_signatureを行っている。差分でいうとpathがprojectではなくjobの持っているpathになっていること。名前から察するにgem_rbs_collectionやRBS本体が持っているライブラリのRBSのSyntaxチェックとかだろうか。

when ValidateLibrarySignatureJob
  if job.guid == current_type_check_guid
    Steep.logger.info { "Processing ValidateLibrarySignature for guid=#{job.guid}, path=#{job.path}" }

    formatter = Diagnostic::LSPFormatter.new({}, **{})
    diagnostics = service.validate_signature(path: job.path, target: job.target)

    typecheck_progress(path: job.path, guid: job.guid, target: job.target, diagnostics: diagnostics.filter_map { formatter.format(_1) })
  end

TypeCheckCodeJob

service.typecheck_sourceを実行している。直前で出てくる変数名やtypecheck_sourceというメソッド名がいかにもアプリケーションの型検査していますと言っている。

when TypeCheckCodeJob
  if job.guid == current_type_check_guid
    Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}, target=#{job.target.name}" }
    group_target = project.group_for_source_path(job.path) || job.target
    formatter = Diagnostic::LSPFormatter.new(group_target.code_diagnostics_config)
    relative_path = project.relative_path(job.path)
    diagnostics = service.typecheck_source(path: relative_path, target: job.target)
    typecheck_progress(path: job.path, guid: job.guid, target: job.target, diagnostics: diagnostics&.filter_map { formatter.format(_1) })
  end

ここまでで、型検査自体はservice.typecheck_source、Syntaxチェックなどはservice.validate_signatureを追っていけば良さそうなあたりがついた。

WorkspaceSymbolJobStatsJobGotoJob

標準入力に何か入力していそうだけど、型検査自体とは無関係と見て良さそう。

when WorkspaceSymbolJob
  writer.write(
    id: job.id,
    result: workspace_symbol_result(job.query)
  )
when StatsJob
  writer.write(
    id: job.id,
    result: stats_result().map(&:as_json)
  )
when GotoJob
  writer.write(
    id: job.id,
    result: goto(job)
  )
end

以後型検査周りはservice.typecheck_sourceservice.validate_signatureを追っていけば良さそうなあたりがついた。今興味があるのは型検査部分なので、ひとまずservice.typecheck_sourceを追い、時間が余ればservice.validate_signatureも見ていく感じとしていきたい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?