Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
environmentName:
- 252
- 253
- 261
fail-fast: false
steps:
- name: Checkout code
Expand Down
13 changes: 0 additions & 13 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,7 @@ classes/
dependencies/
/helpers/venv/


# oauth properties files
secret.properties
# old location of twitter properties
intellij-plugin/hs-Kotlin/resources/twitter/kotlin_koans/oauth_twitter.properties
intellij-plugin/hs-core/resources/twitter/oauth_twitter.properties
intellij-plugin/hs-core/resources/stepik/stepik.properties
intellij-plugin/hs-core/resources/hyperskill/hyperskill-oauth.properties
intellij-plugin/hs-core/resources/linkedin/linkedin-oauth.properties
intellij-plugin/hs-core/resources/marketplace/marketplace-oauth.properties
intellij-plugin/hs-core/resources/lti/lti-auth.properties
#AES key
hs-edu-format/resources/aes/aes.properties
intellij-plugin/hs-core/resources/aes/aes.properties
# don't commit changes in hyperskill css
intellij-plugin/hs-core/resources/style/hyperskill_task.css

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.gradle.jvm.tasks.Jar
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.extensions.intellijPlatform

plugins {
Expand Down Expand Up @@ -66,6 +65,6 @@ dependencies {

intellijPlatform {
testIntellijPlugins(commonTestPlugins)
testFramework(TestFrameworkType.Bundled)
testIntellijPlatformFramework(project)
}
}
23 changes: 19 additions & 4 deletions buildSrc/src/main/kotlin/intellijUtils.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import org.gradle.api.Project
import org.gradle.process.JavaForkOptions
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformDependenciesExtension
import kotlin.reflect.KProperty

Expand All @@ -14,7 +15,7 @@ private const val IDE_RIDER = "rider"
val Project.environmentName: String by Properties

val Project.pluginVersion: String by Properties
val Project.platformVersion: String get() = "20${StringBuilder(environmentName).insert(environmentName.length - 1, '.')}"
val Project.platformVersion: String get() = "20${StringBuilder(environmentName).insert(2, '.')}"
val Project.baseIDE: String by Properties

val Project.ideaVersion: String by Properties
Expand Down Expand Up @@ -78,7 +79,7 @@ val Project.jvmPlugins: List<String>
get() = listOf(
javaPlugin,
"JUnit",
"org.jetbrains.plugins.gradle"
"com.intellij.gradle",
)

val Project.javaScriptPlugins: List<String>
Expand All @@ -94,7 +95,11 @@ val Project.rustPlugins: List<String>
)

val Project.cppPlugins: List<String>
get() = listOf(
get() = listOfNotNull(
baseVersion.toTypeWithVersion()
.version
.takeUnless { /* TODO remove with 252 */ it.startsWith("2025.2") }
?.let { "com.intellij.cmake" },
"com.intellij.cidr.lang",
"com.intellij.clion",
"com.intellij.nativeDebug",
Expand Down Expand Up @@ -134,7 +139,10 @@ fun IntelliJPlatformDependenciesExtension.intellijIde(versionWithCode: String) {
// Starting from 2025.3, IntelliJ IDEA Community and Ultimate are unified into a single distribution.
// Use the new intellijIdea() helper which resolves the unified artifact.
// See: https://blog.jetbrains.com/platform/2025/11/intellij-platform-2025-3-what-plugin-developers-should-know/
if (type == IntelliJPlatformType.IntellijIdeaUltimate && version.startsWith("2025.3")) {
if (type == IntelliJPlatformType.IntellijIdeaUltimate
&& !version.startsWith("2025.2") /* TODO remove with 252 */
&& !version.startsWith("252")
) {
intellijIdea(version) {
useInstaller.set(false)
useCache.set(true)
Expand Down Expand Up @@ -177,6 +185,13 @@ fun IntelliJPlatformDependenciesExtension.testIntellijPlugins(notations: List<St
testIntellijPlugins(*notations.toTypedArray())
}

fun IntelliJPlatformDependenciesExtension.testIntellijPlatformFramework(
project: Project,
frameworkType: TestFrameworkType = TestFrameworkType.Platform,
) {
testFramework(frameworkType, project.baseVersion.toTypeWithVersion().version)
}

// Since 2024.1 CLion has two sets of incompatible plugins: based on classic language engine and new one (AKA Radler).
// Platform uses `idea.suppressed.plugins.set.selector` system property to choose which plugins should be disabled.
// But there aren't `idea.suppressed.plugins.set.selector`, `idea.suppressed.plugins.set.classic`
Expand Down
10 changes: 10 additions & 0 deletions gradle-261.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
customSinceBuild=261
customUntilBuild=261.*

# Existent IDE versions can be found in the following repos:
# https://www.jetbrains.com/intellij-repository/releases/
# https://www.jetbrains.com/intellij-repository/snapshots/
ideaVersion=IU-261.21849-EAP-CANDIDATE-SNAPSHOT
clionVersion=CL-261.21849-EAP-CANDIDATE-SNAPSHOT
pycharmVersion=PC-261.21849-EAP-CANDIDATE-SNAPSHOT
riderVersion=RD-2026.1-SNAPSHOT
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# supported values: 252, 253
environmentName=253
# supported values: 252, 253, 261
environmentName=261

pluginVersion=2026.6
pluginVersion=2026.8

# type of IDE (IDEA, CLion, etc.) used to build/test running
# for more details see `Different IDEs` section in `PlatformVersions.md`
Expand Down
3 changes: 2 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
educational-ml-library = "1.0.65"
jackson = "2.17.2"
kotlin = "2.2.0"
kotlin = "2.3.0"
okhttp = "4.12.0"
retrofit = "2.9.0"

Expand Down Expand Up @@ -29,6 +29,7 @@ kotlin-test-junit = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit"
mockk = { group = "io.mockk", name = "mockk", version = "1.13.13" }
mockwebserver = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okhttp" }
openTest4J = { group = "org.opentest4j", name = "opentest4j", version = "1.3.0" }
hamcrest = { group = "org.hamcrest", name = "hamcrest", version="2.2" }

[plugins]
intelliJPlatformPlugin = { id = "org.jetbrains.intellij.platform", version = "2.10.5" }
Expand Down
3 changes: 0 additions & 3 deletions intellij-plugin/branches/252/resources/plugin_platform.xml

This file was deleted.

3 changes: 0 additions & 3 deletions intellij-plugin/branches/253/resources/plugin_platform.xml

This file was deleted.

3 changes: 1 addition & 2 deletions intellij-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType.*
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.extensions.IntelliJPlatformTestingExtension
import org.jetbrains.intellij.platform.gradle.tasks.PrepareSandboxTask
import org.jetbrains.intellij.platform.gradle.tasks.RunIdeTask
Expand Down Expand Up @@ -94,7 +93,7 @@ dependencies {
// hs-remote-env is excluded - doesn't compile with 2025.2+
pluginModule(implementation(project("hs-localization")))

testFramework(TestFrameworkType.Bundled)
testIntellijPlatformFramework(project)
testIntellijPlugins(commonTestPlugins)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import com.jetbrains.rider.projectView.SolutionDescriptionFactory
internal fun createExistingSolutionDescription(solutionPath: String) =
SolutionDescriptionFactory.existing(solutionPath)

internal fun String.asRdPath(): String = this

/**
* Helper class to hold test result data across platform versions.
* In 252, this data comes from RdUnitTestResultData.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.jetbrains.rider.projectView.SolutionDescriptionFactory
internal fun createExistingSolutionDescription(solutionPath: String) =
SolutionDescriptionFactory.existing(solutionPath, displayName = null)

internal fun String.asRdPath(): String = this

/**
* Helper class to hold test result data across platform versions.
* In 252, this data comes from RdUnitTestResultData.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.hyperskill.academy.csharp

import com.intellij.openapi.project.Project
import com.jetbrains.rd.ide.model.RdPath
import com.jetbrains.rider.model.RdUnitTestSession
import com.jetbrains.rider.projectView.SolutionDescriptionFactory

// In 253, SolutionDescriptionFactory.existing requires a displayName parameter
internal fun createExistingSolutionDescription(solutionPath: String) =
SolutionDescriptionFactory.existing(solutionPath, displayName = null)

internal fun String.asRdPath(): RdPath = RdPath("local", this)

/**
* Helper class to hold test result data across platform versions.
* In 252, this data comes from RdUnitTestResultData.
* In 253, the API changed significantly and we construct this from available sources.
*/
data class TestResultData(
val exceptionLines: String
)

// In 253, resultData property was removed from RdUnitTestSession
// The test result output is now accessed differently through the session protocol
// For now, we provide a no-op implementation - tests will pass/fail but without detailed output
internal fun adviseResultData(
@Suppress("UNUSED_PARAMETER") project: Project,
@Suppress("UNUSED_PARAMETER") rdSession: RdUnitTestSession,
@Suppress("UNUSED_PARAMETER") nodeId: Int,
@Suppress("UNUSED_PARAMETER") callback: (TestResultData) -> Unit
) {
// TODO: BACKCOMPAT 253 - The resultData API was removed in 253.
// Need to find the replacement API for getting detailed test failure output.
// For now, the callback is not invoked, which means detailed error messages
// won't be available, but test pass/fail status will still work.
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,14 @@ class CSharpBackendService(private val project: Project, private val scope: Coro

when (request) {
is CsprojRequest.Add -> {
val taskPaths = request.tasks.map { it.csProjPathByTask(project) }
val parentId = project.getSolutionEntity()?.getId(project) ?: return
val projectFiles = request.tasks
.asSequence()
.map { it.csProjPathByTask(project) }
.map { it.asRdPath() }
.toList()
val parameters = RdPostProcessParameters(false, listOf())
val addCommand = AddProjectCommand(parentId, taskPaths, listOf(), true, parameters)
val addCommand = AddProjectCommand(parentId, projectFiles, listOf(), true, parameters)

try {
project.solution.projectModelTasks.addProject.runCommandUnderProgress(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperskill.academy.cpp.checker

import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.openapi.project.Project
import com.jetbrains.cidr.cpp.execution.testing.tcatch.CMakeCatchTestRunConfigurationType
import org.hyperskill.academy.cpp.CppCatchCourseBuilder
import org.hyperskill.academy.cpp.CppConfigurator
import org.hyperskill.academy.cpp.CppProjectSettings
import org.hyperskill.academy.learning.EduCourseBuilder
import org.hyperskill.academy.learning.checker.TaskChecker
import org.hyperskill.academy.learning.checker.TaskCheckerProvider
import org.hyperskill.academy.learning.courseFormat.tasks.EduTask

class CppCatchConfigurator : CppConfigurator() {
override val courseBuilder: EduCourseBuilder<CppProjectSettings>
get() = CppCatchCourseBuilder()

override val taskCheckerProvider: TaskCheckerProvider =
object : CppTaskCheckerProvider() {
override fun getEduTaskChecker(task: EduTask, project: Project): TaskChecker<EduTask> =
object : CppEduTaskChecker(task, envChecker, project) {
override fun getFactory(): ConfigurationFactory =
CMakeCatchTestRunConfigurationType.getInstance().getFactory()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperskill.academy.cpp.checker

import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.openapi.project.Project
import com.jetbrains.cidr.cpp.execution.testing.google.CMakeGoogleTestRunConfigurationType
import org.hyperskill.academy.cpp.CppConfigurator
import org.hyperskill.academy.cpp.CppGTestCourseBuilder
import org.hyperskill.academy.cpp.CppProjectSettings
import org.hyperskill.academy.learning.EduCourseBuilder
import org.hyperskill.academy.learning.checker.TaskChecker
import org.hyperskill.academy.learning.checker.TaskCheckerProvider
import org.hyperskill.academy.learning.courseFormat.tasks.EduTask

class CppGTestConfigurator : CppConfigurator() {
override val courseBuilder: EduCourseBuilder<CppProjectSettings>
get() = CppGTestCourseBuilder()

override val taskCheckerProvider: TaskCheckerProvider =
object : CppTaskCheckerProvider() {
override fun getEduTaskChecker(task: EduTask, project: Project): TaskChecker<EduTask> =
object : CppEduTaskChecker(task, envChecker, project) {
override fun getFactory(): ConfigurationFactory =
CMakeGoogleTestRunConfigurationType.getInstance().getFactory()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperskill.academy.cpp.checker

import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.openapi.project.Project
import com.jetbrains.cidr.cpp.execution.testing.tcatch.CMakeCatchTestRunConfigurationType
import org.hyperskill.academy.cpp.CppCatchCourseBuilder
import org.hyperskill.academy.cpp.CppConfigurator
import org.hyperskill.academy.cpp.CppProjectSettings
import org.hyperskill.academy.learning.EduCourseBuilder
import org.hyperskill.academy.learning.checker.TaskChecker
import org.hyperskill.academy.learning.checker.TaskCheckerProvider
import org.hyperskill.academy.learning.courseFormat.tasks.EduTask

class CppCatchConfigurator : CppConfigurator() {
override val courseBuilder: EduCourseBuilder<CppProjectSettings>
get() = CppCatchCourseBuilder()

override val taskCheckerProvider: TaskCheckerProvider =
object : CppTaskCheckerProvider() {
override fun getEduTaskChecker(task: EduTask, project: Project): TaskChecker<EduTask> =
object : CppEduTaskChecker(task, envChecker, project) {
override fun getFactory(): ConfigurationFactory =
CMakeCatchTestRunConfigurationType.getInstance().getFactory()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperskill.academy.cpp.checker

import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.openapi.project.Project
import com.jetbrains.cidr.cpp.execution.testing.google.CMakeGoogleTestRunConfigurationType
import org.hyperskill.academy.cpp.CppConfigurator
import org.hyperskill.academy.cpp.CppGTestCourseBuilder
import org.hyperskill.academy.cpp.CppProjectSettings
import org.hyperskill.academy.learning.EduCourseBuilder
import org.hyperskill.academy.learning.checker.TaskChecker
import org.hyperskill.academy.learning.checker.TaskCheckerProvider
import org.hyperskill.academy.learning.courseFormat.tasks.EduTask

class CppGTestConfigurator : CppConfigurator() {
override val courseBuilder: EduCourseBuilder<CppProjectSettings>
get() = CppGTestCourseBuilder()

override val taskCheckerProvider: TaskCheckerProvider =
object : CppTaskCheckerProvider() {
override fun getEduTaskChecker(task: EduTask, project: Project): TaskChecker<EduTask> =
object : CppEduTaskChecker(task, envChecker, project) {
override fun getFactory(): ConfigurationFactory =
CMakeGoogleTestRunConfigurationType.getInstance().getFactory()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperskill.academy.cpp.checker

import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.openapi.project.Project
import com.jetbrains.cidr.execution.testing.tcatch.CidrCatchTestRunConfigurationType
import org.hyperskill.academy.cpp.CppCatchCourseBuilder
import org.hyperskill.academy.cpp.CppConfigurator
import org.hyperskill.academy.cpp.CppProjectSettings
import org.hyperskill.academy.learning.EduCourseBuilder
import org.hyperskill.academy.learning.checker.TaskChecker
import org.hyperskill.academy.learning.checker.TaskCheckerProvider
import org.hyperskill.academy.learning.courseFormat.tasks.EduTask

class CppCatchConfigurator : CppConfigurator() {
override val courseBuilder: EduCourseBuilder<CppProjectSettings>
get() = CppCatchCourseBuilder()

override val taskCheckerProvider: TaskCheckerProvider =
object : CppTaskCheckerProvider() {
override fun getEduTaskChecker(task: EduTask, project: Project): TaskChecker<EduTask> =
object : CppEduTaskChecker(task, envChecker, project) {
override fun getFactory(): ConfigurationFactory =
CidrCatchTestRunConfigurationType.getInstance().getFactory()
}
}
}
Loading
Loading