diff --git a/gradle.properties b/gradle.properties index 458991097..ed965b717 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ # supported values: 252, 253 environmentName=253 -pluginVersion=2026.3 +pluginVersion=2026.6 # type of IDE (IDEA, CLion, etc.) used to build/test running # for more details see `Different IDEs` section in `PlatformVersions.md` diff --git a/intellij-plugin/hs-core/src/org/hyperskill/academy/coursecreator/validation/CourseValidationHelper.kt b/intellij-plugin/hs-core/src/org/hyperskill/academy/coursecreator/validation/CourseValidationHelper.kt index 8c7f1beb1..15f4874d0 100644 --- a/intellij-plugin/hs-core/src/org/hyperskill/academy/coursecreator/validation/CourseValidationHelper.kt +++ b/intellij-plugin/hs-core/src/org/hyperskill/academy/coursecreator/validation/CourseValidationHelper.kt @@ -95,7 +95,8 @@ class CourseValidationHelper( } private suspend fun TestSuiteBuilder.validateTaskDescriptionLinks(project: Project, task: Task) { - val text = readAction { task.getFormattedTaskText(project) } ?: return + val text = task.getFormattedTaskText(project) + ?: return val links = extractLinks(project, task, text) // Don't create empty node if no links in the task description if (links.isEmpty()) return diff --git a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/StudyItemExt.kt b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/StudyItemExt.kt index 99aa03ae5..ac9b4c28e 100644 --- a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/StudyItemExt.kt +++ b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/StudyItemExt.kt @@ -30,7 +30,9 @@ fun StudyItem.getDir(courseDir: VirtualFile): VirtualFile? { lessonParent.getDir(courseDir)?.findFileByRelativePath(lessonParent.getPathToChildren())?.findChild(name) } - is Task -> (parentOrNull as? Lesson)?.getDir(courseDir)?.let { findDir(it) } + is Task -> (parentOrNull as? Lesson) + ?.getDir(courseDir) + ?.findChild(targetDirName) else -> error("Can't find directory for the item $itemType") } } diff --git a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/TaskExt.kt b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/TaskExt.kt index f1f5cb4fa..fb9c162bd 100644 --- a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/TaskExt.kt +++ b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/courseFormat/ext/TaskExt.kt @@ -15,12 +15,14 @@ import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiFile import com.intellij.psi.PsiManager import com.intellij.psi.util.PsiUtilCore +import com.intellij.util.SlowOperations import com.intellij.util.concurrency.annotations.RequiresReadLock import org.hyperskill.academy.learning.EduUtilsKt.convertToHtml import org.hyperskill.academy.learning.courseDir import org.hyperskill.academy.learning.courseFormat.* import org.hyperskill.academy.learning.courseFormat.EduFormatNames.TASK import org.hyperskill.academy.learning.courseFormat.hyperskill.HyperskillCourse +import org.hyperskill.academy.learning.courseFormat.tasks.CodeTask import org.hyperskill.academy.learning.courseFormat.tasks.Task import org.hyperskill.academy.learning.courseFormat.tasks.TheoryTask import org.hyperskill.academy.learning.courseGeneration.GeneratorUtils @@ -46,9 +48,13 @@ val Task.dirName: String return TASK } -fun Task.findDir(lessonDir: VirtualFile?): VirtualFile? { - return lessonDir?.findChild(dirName) -} +val Task.targetDirName: String + get() = when (this) { + is TheoryTask, + is CodeTask -> name + + else -> dirName + } fun Task.findSourceDir(taskDir: VirtualFile): VirtualFile? { val sourceDir = sourceDir ?: return null @@ -109,7 +115,7 @@ fun Task.getDescriptionFile( ): VirtualFile? { val taskDirectory = getTaskDirectory(project) ?: return null - val file = com.intellij.util.SlowOperations.knownIssue("EDU-8086").use { + val file = SlowOperations.knownIssue("EDU-8086").use { if (guessFormat) { taskDirectory.run { findChild(DescriptionFormat.HTML.fileName) ?: findChild(DescriptionFormat.MD.fileName) } } @@ -186,9 +192,11 @@ private fun VirtualFile.toDescriptionFormat(): DescriptionFormat = DescriptionFormat.values().firstOrNull { it.extension == extension } ?: loadingError(EduCoreBundle.message("yaml.editor.invalid.description")) -@RequiresReadLock fun Task.getFormattedTaskText(project: Project): String? { - var text = getTaskText(project) ?: return null + var text = runReadAction { + getTaskText(project) + } ?: return null + text = StringUtil.replace(text, "%IDE_NAME%", ApplicationNamesInfo.getInstance().fullProductName) val textBuffer = StringBuffer(text) replaceActionIDsWithShortcuts(textBuffer) diff --git a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/stepik/hyperskill/courseGeneration/HyperskillTaskBuilder.kt b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/stepik/hyperskill/courseGeneration/HyperskillTaskBuilder.kt index 53fe900bc..abcb28e06 100644 --- a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/stepik/hyperskill/courseGeneration/HyperskillTaskBuilder.kt +++ b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/stepik/hyperskill/courseGeneration/HyperskillTaskBuilder.kt @@ -6,8 +6,6 @@ import org.hyperskill.academy.learning.courseFormat.CheckStatus import org.hyperskill.academy.learning.courseFormat.Course import org.hyperskill.academy.learning.courseFormat.EduFileErrorHighlightLevel import org.hyperskill.academy.learning.courseFormat.tasks.* -import org.hyperskill.academy.learning.courseFormat.tasks.EduTask.Companion.PYCHARM_TASK_TYPE -import org.hyperskill.academy.learning.courseFormat.tasks.RemoteEduTask.Companion.REMOTE_EDU_TASK_TYPE import org.hyperskill.academy.learning.stepik.PyCharmStepOptions import org.hyperskill.academy.learning.stepik.StepikTaskBuilder import org.hyperskill.academy.learning.stepik.hasHeaderOrFooter @@ -25,17 +23,13 @@ class HyperskillTaskBuilder( return HyperskillLanguages.getLanguageName(language.id) } - fun build(): Task? { - val blockName = stepSource.block?.name ?: return null + fun build(): Task? = when (val blockName = stepSource.block?.name) { + EduTask.PYCHARM_TASK_TYPE if stepSource.isRemoteTested -> createTask(RemoteEduTask.REMOTE_EDU_TASK_TYPE) + EduTask.PYCHARM_TASK_TYPE, + "text", + CodeTask.CODE_TASK_TYPE -> createTask(blockName) - val type = if (blockName == PYCHARM_TASK_TYPE && stepSource.isRemoteTested) { - REMOTE_EDU_TASK_TYPE - } - else { - blockName - } - - return createTask(type) + else -> null } override fun createTask(type: String): Task { diff --git a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/taskToolWindow/ui/TaskToolWindow.kt b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/taskToolWindow/ui/TaskToolWindow.kt index c5fdd3021..7a724229f 100644 --- a/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/taskToolWindow/ui/TaskToolWindow.kt +++ b/intellij-plugin/hs-core/src/org/hyperskill/academy/learning/taskToolWindow/ui/TaskToolWindow.kt @@ -16,7 +16,6 @@ package org.hyperskill.academy.learning.taskToolWindow.ui import com.intellij.openapi.Disposable -import com.intellij.openapi.application.runReadAction import com.intellij.openapi.project.Project import com.intellij.openapi.util.registry.Registry import com.intellij.util.ui.update.MergingUpdateQueue @@ -65,10 +64,8 @@ abstract class TaskToolWindow(protected val project: Project) : Disposable { const val TASK_DESCRIPTION_UPDATE_DELAY_REGISTRY_KEY: String = "hyperskill.task.description.update.delay" fun getTaskDescription(project: Project, task: Task?, uiMode: JavaUILibrary): String { - val openedTask = task ?: return EduCoreBundle.message("label.open.task") - val taskText = runReadAction { - openedTask.getFormattedTaskText(project) - } ?: return EduCoreBundle.message("label.open.task") + val taskText = task?.getFormattedTaskText(project) + ?: return EduCoreBundle.message("label.open.task") val transformerContext = HtmlTransformerContext(project, task, uiMode) return TaskDescriptionTransformer.transform(taskText, transformerContext) }