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

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

2週間遅れております。

### `Steep::Services::TypeCheckService#type_check_file`

`Source.parse`は内部で[parser gem](https://github.com/whitequark/parser)を利用しています。steepアノテーションを拾ってるみたいですね。拾ったアノテーションは`Steep::AST::Annotation::Collection`で仕分けされてます。`TypeCheckService.type_check`からは何してるのか全然わからない...。

```rb
def type_check_file(target:, subtyping:, path:, text:)
  Steep.logger.tagged "#type_check_file(#{path}@#{target.name})" do
    source = Source.parse(text, path: path, factory: subtyping.factory)
    typing = TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: yield, cursor: nil)
    ignores = Source::IgnoreRanges.new(ignores: source.ignores)
    SourceFile.with_typing(path: path, content: text, node: source.node, typing: typing, ignores: ignores)
  end
rescue AnnotationParser::SyntaxError => exn
  error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: exn.location)
  SourceFile.with_syntax_error(path: path, content: text, error: error)
rescue ::Parser::SyntaxError => exn
  error = Diagnostic::Ruby::SyntaxError.new(message: exn.message, location: (_ = exn).diagnostic.location)
  SourceFile.with_syntax_error(path: path, content: text, error: error)
rescue EncodingError => exn
  SourceFile.no_data(path: path, content: "")
rescue RuntimeError => exn
  Steep.log_error(exn)
  SourceFile.no_data(path: path, content: text)
end
```

### `TypeCheckService#.type_check`

`subtyping.factory`は`Steep::AST::Types::Factory`オブジェクトであり、`subtyping.factory.definition_builder`は`RBS::DefinitionBuilder.new(env: env)`であり、`build_instance(AST::Builtin::Object.module_name)`とはつまり、`RBS::DefinitionBuilder.new(env: env).build_instance(AST::Builtin::Object.module_name)`...。ということはdefinitionとはRBS定義を表現するオブジェクトかなぁ。

annotationとdefinitionで型情報が揃うので、それをtypingとして返しているのかな...？

```rb
def self.type_check(source:, subtyping:, constant_resolver:, cursor:)
  annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)

  definition = subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name)

  const_env = TypeInference::ConstantEnv.new(
    factory: subtyping.factory,
    context: nil,
    resolver: constant_resolver
  )
  type_env = TypeInference::TypeEnv.new(const_env)
  type_env = TypeInference::TypeEnvBuilder.new(
    TypeInference::TypeEnvBuilder::Command::ImportConstantAnnotations.new(annotations),
    TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(subtyping.factory),
    TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(definition, subtyping.factory),
    TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableAnnotations.new(annotations),
    TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annotations)
  ).build(type_env)

  context = TypeInference::Context.new(
    block_context: nil,
    module_context: TypeInference::Context::ModuleContext.new(
      instance_type: AST::Builtin::Object.instance_type,
      module_type: AST::Builtin::Object.module_type,
      implement_name: nil,
      nesting: nil,
      class_name: AST::Builtin::Object.module_name,
      instance_definition: subtyping.factory.definition_builder.build_instance(AST::Builtin::Object.module_name),
      module_definition: subtyping.factory.definition_builder.build_singleton(AST::Builtin::Object.module_name)
    ),
    method_context: nil,
    break_context: nil,
    self_type: AST::Builtin::Object.instance_type,
    type_env: type_env,
    call_context: TypeInference::MethodCall::TopLevelContext.new,
    variable_context: TypeInference::Context::TypeVariableContext.empty
  )

  typing = Typing.new(source: source, root_context: context, cursor: cursor)

  construction = TypeConstruction.new(
    checker: subtyping,
    annotations: annotations,
    source: source,
    context: context,
    typing: typing
  )

  construction.synthesize(source.node) if source.node

  typing
end
```

うーん、ちゃんと理解するにはじっくり読む必要がありそう。隙間時間で理解できるようなものじゃない気がしてきたなぁ。

~~type_check_fileはRBS定義のSyntaxErrorなどを検査をしながら最終的に型情報のオブジェクトを返している、ような気がする。~~ 違いました。

steepのアノテーションを増やしたいとか何か問題を見つけたら`Steep::AST::Annotation::Collection`を見るとよさそうなのはわかった。