fun loadCourse()

in intellij-plugin/educational-core/src/com/jetbrains/edu/learning/yaml/YamlDeepLoader.kt [37:102]


  fun loadCourse(project: Project): Course? {
    val projectDir = project.courseDir

    @NonNls
    val errorMessageToLog = "Course yaml config cannot be null"
    val courseConfig = projectDir.findChild(YamlConfigSettings.COURSE_CONFIG) ?: error(errorMessageToLog)

    // the initial mapper has no idea whether the course is in the CC or in the Student mode
    val initialMapper = YamlMapper.basicMapper()
    initialMapper.setupForMigration(project)
    val deserializedCourse = deserializeItemProcessingErrors(courseConfig, project, mapper=initialMapper) as? Course ?: return null
    val needMigration = YamlMigrator(initialMapper).needMigration()

    // this mapper already respects course mode, it will be used to deserialize all other course items
    val mapper = deserializedCourse.mapper()
    mapper.setupForMigration(project)
    mapper.setEduValue(YAML_VERSION_MAPPER_KEY, initialMapper.getEduValue(YAML_VERSION_MAPPER_KEY))

    deserializedCourse.items = deserializedCourse.deserializeContent(project, deserializedCourse.items, mapper)
    deserializedCourse.items.forEach { deserializedItem ->
      when (deserializedItem) {
        is Section -> {
          // set parent to correctly obtain dirs in deserializeContent method
          deserializedItem.parent = deserializedCourse
          deserializedItem.items = deserializedItem.deserializeContent(project, deserializedItem.items, mapper)
          deserializedItem.lessons.forEach {
            it.parent = deserializedItem
            it.items = it.deserializeContent(project, it.taskList, mapper)
          }
        }
        is Lesson -> {
          // set parent to correctly obtain dirs in deserializeContent method
          deserializedItem.parent = deserializedCourse
          deserializedItem.items = deserializedItem.deserializeContent(project, deserializedItem.taskList, mapper)
          addNonEditableFilesToCourse(deserializedItem, deserializedCourse, project)
          deserializedItem.removeNonExistingTaskFiles(project)
        }
      }
    }

    if (needMigration) {
      project.invokeLater {
        // After migration, we save all YAMLs back to disk.
        // In theory, com.jetbrains.edu.learning.yaml.YamlLoader.loadItem() could be fired before the migrated YAMLs are saved,
        // and that could lead to incorrectly read YAML.
        // One of the dangerous places: the FileEditorManagerListener calls loadItem() to refresh editor notifications for
        // YAML files, and this happens right after the project is loaded.
        YamlFormatSynchronizer.saveAll(project)
      }
    }

    // we initialize course before setting description and remote info, as we have to set parent item
    // to obtain description/remote config file to set info from
    deserializedCourse.init(true)
    deserializedCourse.loadRemoteInfoRecursively(project)

    if (deserializedCourse is HyperskillCourse) {
      project.isHyperskillProject = true
      return null
    }

    if (!deserializedCourse.isStudy) {
      deserializedCourse.setDescriptionInfo(project)
    }
    return deserializedCourse
  }