Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-IDE Support and more Run-Configurations #88

Merged
merged 23 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5f1f5dd
updated gradle
Kroko-fant Mar 17, 2023
029f3e9
updated dependencies for intellij 2023.1
Kroko-fant Apr 19, 2023
5057e3c
updated dsl 1 to dsl 2
Kroko-fant Apr 23, 2023
5e5bf87
updated patch notes
Kroko-fant Apr 23, 2023
67d0915
Merge remote-tracking branch 'origin/main'
Kroko-fant Apr 24, 2023
8fed81c
Changed Path UI to make the full path visible if the window is big en…
Kroko-fant Mar 17, 2023
2b0a048
Update CommitMessageChooser.kt
Kroko-fant May 2, 2023
f0a1e19
improved code quality
Kroko-fant May 8, 2023
76e863e
Made AnAction implement getActionUpdateThread() method
Kroko-fant May 10, 2023
c9d5b2e
fixed a bug that resulted in orion not detecting excercises
Kroko-fant May 28, 2023
f167870
fixed pipeline and changed base url back to the current one https://a…
Kroko-fant Jun 1, 2023
fa78d1e
Normalize all the line endings
Kroko-fant Jun 1, 2023
29feba1
Empty-Commit
Kroko-fant Jun 2, 2023
89449b5
Empty-Commit
Kroko-fant Jun 2, 2023
afa7871
Merge remote-tracking branch 'origin/main' into development
Kroko-fant Jun 5, 2023
5447e04
Merge branch 'ls1intum:main' into main
Kroko-fant Jun 5, 2023
a516cec
Merge branch 'refactoring' into development
Kroko-fant Jun 5, 2023
845f10f
Merge branch 'refactoring'
Kroko-fant Jun 5, 2023
c360c8f
Gradle Run Configuration
Kroko-fant Jun 15, 2023
d946ef0
Gradle Run Configuration
Kroko-fant Jun 22, 2023
0c989de
Added support to select SDKs
Kroko-fant Jun 28, 2023
4f9e4ca
fixed pipeline
Kroko-fant Jun 28, 2023
05e73ba
updated plugin version
Kroko-fant Sep 7, 2023
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
12 changes: 6 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("java")
kotlin("jvm") version "1.8.10"
id("org.jetbrains.intellij") version "1.13.3"
kotlin("jvm") version "1.9.0"
id("org.jetbrains.intellij") version "1.15.0"
}

java {
Expand All @@ -30,17 +30,17 @@ dependencies {
// See /~https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
pluginName.set("orion")
version.set("2023.1")
plugins.set(listOf("Git4Idea", "maven", "PythonCore:231.8109.144"))
version.set("2023.2.1")
plugins.set(listOf("Git4Idea", "PythonCore:232.9559.62", "maven", "gradle"))
}

tasks {
patchPluginXml {
// Last 2 digits of the year and the major version digit, 211-211.* equals (20)21.1.*
// See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
sinceBuild.set("231")
sinceBuild.set("232")
// Orion Plugin version. Needs to be incremented for every new release!
version.set("1.2.3")
version.set("1.2.4")
changeNotes.set(
"""<p>
<h1>Removed Deprecation</h1>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.components.service
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.StartupActivity
import com.intellij.openapi.startup.ProjectActivity
import de.tum.www1.orion.connector.client.JavaScriptConnector
import de.tum.www1.orion.connector.ide.vcs.submit.ChangeSubmissionContext
import de.tum.www1.orion.enumeration.ExerciseView
Expand All @@ -19,15 +19,15 @@ import de.tum.www1.orion.util.OrionAssessmentUtils
import de.tum.www1.orion.util.appService
import de.tum.www1.orion.util.translate

class OrionStartupProjectRefreshActivity : StartupActivity, DumbAware {
class OrionStartupProjectRefreshActivity : ProjectActivity, DumbAware {

/**
* Runs all pending jobs on opening a programming exercise project. For now, this includes:
* - Registering the opened exercise in the registry
* - Pull all changes from the remote
* - Tell the Artemis webapp that a new exercise was opened
*/
override fun runActivity(project: Project) {
override suspend fun execute(project: Project) {
// We need to subscribe to all internal state listeners before any message could potentially be sent
project.service<JavaScriptConnector>().initIDEStateListeners()
// If the exercise was opened for the first time
Expand Down Expand Up @@ -64,4 +64,6 @@ class OrionStartupProjectRefreshActivity : StartupActivity, DumbAware {
project.service<OrionExerciseService>().updateExercise()
}
}


}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package de.tum.www1.orion.build.instructor
package de.tum.www1.orion.build

import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.openapi.application.ApplicationInfo
import com.intellij.openapi.project.Project
import de.tum.www1.orion.build.instructor.JavaRunConfigurationProvider
import de.tum.www1.orion.build.instructor.OrionInstructorBuildUtil
import de.tum.www1.orion.enumeration.ProgrammingLanguage
import de.tum.www1.orion.util.selectedProgrammingLanguage
import java.io.File.separatorChar
Expand All @@ -11,30 +14,39 @@ import java.io.File.separatorChar
*/
object OrionLocalRunConfigurationSettingsFactory {
/**
* Creates a run configuration for maven clean test working in the merged_test directory
* Creates a run configuration working in the merged_test directory
*
* @param project project to generate the configuration for
* @return the configuration
*/
fun runConfigurationForInstructor(project: Project): RunnerAndConfigurationSettings {
fun runConfigurationForInstructor(project: Project): RunnerAndConfigurationSettings? {

return when (project.selectedProgrammingLanguage()) {
ProgrammingLanguage.JAVA -> JavaRunConfigurationProvider(project).provideBuildAndTestRunConfiguration("${project.basePath!!}$separatorChar${OrionInstructorBuildUtil.LOCAL_TEST_DIRECTORY}")
else -> throw IllegalArgumentException("Unsupported programming language for run configuration " + project.selectedProgrammingLanguage())
ProgrammingLanguage.JAVA -> {
//check if its Intellij
val applicationInfo = ApplicationInfo.getInstance().fullApplicationName
if (!applicationInfo.contains("IntelliJ")) {
return null
}

JavaRunConfigurationProvider(project).provideBuildAndTestRunConfiguration("${project.basePath!!}$separatorChar${OrionInstructorBuildUtil.LOCAL_TEST_DIRECTORY}")
}

else -> return null
}
}

/**
* Creates a run configuration for maven clean test working in the base directory
* Creates a run configuration working in the base directory
*
* @param project project to generate the configuration for
* @return the configuration
*/
fun runConfigurationForTutor(project: Project): RunnerAndConfigurationSettings {
fun runConfigurationForTutor(project: Project): RunnerAndConfigurationSettings? {
return when (project.selectedProgrammingLanguage()) {
// maven clean test should work for any language
else -> JavaRunConfigurationProvider(project).provideBuildAndTestRunConfiguration(
project.basePath!!
)
}
}
}
}
4 changes: 2 additions & 2 deletions src/main/java/de/tum/www1/orion/build/OrionTestInterceptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ class OrionTestInterceptor(private val project: Project) : OrionTestParser {
.split(",")
val parent = when {
// child of previous node
previousNode?.level ?: Int.MAX_VALUE < level -> previousNode
(previousNode?.level ?: Int.MAX_VALUE) < level -> previousNode
// same level as parent of previous node
previousNode?.level ?: Int.MIN_VALUE > level -> parentNode!!.parent
(previousNode?.level ?: Int.MIN_VALUE) > level -> parentNode!!.parent
// same level as previous node
else -> parentNode
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,48 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import org.jetbrains.idea.maven.execution.MavenRunConfiguration
import org.jetbrains.idea.maven.execution.MavenRunConfigurationType
import org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType
import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration
import java.io.File

class JavaRunConfigurationProvider(val project: Project) : OrionRunConfigurationProvider {
override fun provideBuildAndTestRunConfiguration(workingDir: String): RunnerAndConfigurationSettings {
/**
* Provides a java run configuration for maven/gradle projects
*/
override fun provideBuildAndTestRunConfiguration(workingDir: String): RunnerAndConfigurationSettings? {


val gradleBuildFile = File("$workingDir/build.gradle")
val mavenBuildFile = File("$workingDir/pom.xml")

val runManager = project.service<RunManager>()
val runConfigurationSettings =
runManager.createConfiguration("Orion Maven Build & Test Locally", MavenRunConfigurationType::class.java)
(runConfigurationSettings.configuration as MavenRunConfiguration).apply {
runnerParameters.apply {
goals = listOf("clean", "test")
workingDirPath = workingDir

// decide between maven and gradle
if (gradleBuildFile.exists() && !gradleBuildFile.isDirectory) {
val gradleRunConfigurationSettings = runManager.createConfiguration(
"Orion Build & Test locally",
GradleExternalTaskConfigurationType::class.java
)
(gradleRunConfigurationSettings.configuration as GradleRunConfiguration).apply {
rawCommandLine = "clean test"

}
}
return gradleRunConfigurationSettings
} else if (mavenBuildFile.exists() && !mavenBuildFile.isDirectory) {
val mavenRunConfigurationSettings =
runManager.createConfiguration(
"Orion Maven Build & Test Locally",
MavenRunConfigurationType::class.java
)
(mavenRunConfigurationSettings.configuration as MavenRunConfiguration).apply {
runnerParameters.apply {

return runConfigurationSettings
goals = listOf("clean", "test")
workingDirPath = workingDir
}
}
return mavenRunConfigurationSettings
}
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
import de.tum.www1.orion.build.OrionLocalRunConfigurationSettingsFactory
import de.tum.www1.orion.dto.RepositoryType
import de.tum.www1.orion.enumeration.ProgrammingLanguage
import de.tum.www1.orion.exercise.registry.OrionStudentExerciseRegistry
Expand Down Expand Up @@ -41,7 +42,7 @@ enum class RepositoryCheckoutPath : CustomizableCheckoutPath {
TEST {
override fun forProgrammingLanguage(language: ProgrammingLanguage): String {
return when (language) {
ProgrammingLanguage.JAVA, ProgrammingLanguage.PYTHON -> ""
ProgrammingLanguage.JAVA, ProgrammingLanguage.PYTHON, ProgrammingLanguage.KOTLIN -> ""
ProgrammingLanguage.C -> "tests"
// runTestsLocally should prevent any other language from reaching this line
else -> throw UnsupportedOperationException(
Expand All @@ -55,6 +56,9 @@ enum class RepositoryCheckoutPath : CustomizableCheckoutPath {
}

class OrionInstructorBuildUtil(val project: Project) {
/**
* A function to run tests locally
*/
fun runTestsLocally() {
val language = project.selectedProgrammingLanguage() ?: return Unit.also {
when (val exerciseLanguage = project.service<OrionStudentExerciseRegistry>().exerciseInfo?.language) {
Expand Down Expand Up @@ -95,9 +99,11 @@ class OrionInstructorBuildUtil(val project: Project) {
)
}
}

// creates a run configuration
val runConfigurationSettings = OrionLocalRunConfigurationSettingsFactory.runConfigurationForInstructor(project)
ExecutionUtil.runConfiguration(runConfigurationSettings, DefaultRunExecutor.getRunExecutorInstance())
if (runConfigurationSettings != null) {
ExecutionUtil.runConfiguration(runConfigurationSettings, DefaultRunExecutor.getRunExecutorInstance())
}
project.messageBus.connect().subscribe(ExecutionManager.EXECUTION_TOPIC, object : ExecutionListener {
override fun processTerminated(
executorId: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package de.tum.www1.orion.build.instructor
import com.intellij.execution.RunnerAndConfigurationSettings

interface OrionRunConfigurationProvider {
fun provideBuildAndTestRunConfiguration(workingDir: String): RunnerAndConfigurationSettings
fun provideBuildAndTestRunConfiguration(workingDir: String): RunnerAndConfigurationSettings?
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import java.util.*
/**
* Represent a class which is responsible for initializing JS to Java communication
*
* When a Java handler is added to a CefBrowser instance (via JBCEFJSQuery wrapper in this case, JCEF will inject into
* When a Java handler is added to a CefBrowser instance (via JBCEFJSQuery wrapper in this case), JCEF will inject into
* the window object of the loaded page's Javascript a cefQuery function. Message to Java can be conducted by invoking
* in JS this function and passing the message. If there are multiple handlers attached, a random handler will receive
* the message. Propagation of message to other handlers is done by setting the return value of onQuery to false. To
* make sure that the message is dispatched to the right handler, we use message of the form:
"handlerName \n param1 \n param2 \n param3 \n ...
* "handlerName \n param1 \n param2 \n param3 \n ..."
* See https://appdoc.app/artifact/org.bitbucket.johness/java-cef/49.87.win32.2/index.html?org/cef/handler/CefRequestHandler.html
* for more information.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ interface IOrionExerciseConnector {
*
* @param submissionId id of the submission, used to navigate to the corresponding URL
* @param correctionRound correction round, also needed to navigate to the correct URL
* @param testRun true if in a test run, also needed for navigation
* @param base64data data of the zip file containing the student's repository
*/
// Uncomment this to activate transfer of the testRun flag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,11 @@ public void determineSubmissionStrategy() {
final var currentView = project.getService(OrionStudentExerciseRegistry.class).getCurrentView();
if (currentView != null) {
switch (currentView) {
case STUDENT:
this.submissionStrategy = new StudentChangeSubmissionStrategy(project);
break;
case INSTRUCTOR:
this.submissionStrategy = new InstructorChangeSubmissionStrategy(project);
break;
default:
case STUDENT -> this.submissionStrategy = new StudentChangeSubmissionStrategy(project);
case INSTRUCTOR -> this.submissionStrategy = new InstructorChangeSubmissionStrategy(project);
default ->
// Tutors may never submit
this.submissionStrategy = null;
break;
this.submissionStrategy = null;
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/de/tum/www1/orion/dto/BuildLogErrors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ data class BuildLogFileErrorsDTO(val fileName: String, val errors: List<BuildErr
other as BuildLogFileErrorsDTO

if (fileName != other.fileName) return false
if (errors != other.errors) return false

return true
return errors == other.errors
}

override fun hashCode(): Int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class OrionExerciseService(private val project: Project) {
cloneFunction: (chosenPath: String, globalRegistry: OrionGlobalExerciseRegistryService) -> Unit
) {
val registry = service<OrionGlobalExerciseRegistryService>()

if (!registry.isImported(exercise.id, exerciseView)) {
runInEdt(ModalityState.NON_MODAL) {
val chooser = ImportPathChooser(project, exercise, exerciseView)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.vfs.VirtualFileManager
import de.tum.www1.orion.build.instructor.OrionLocalRunConfigurationSettingsFactory
import de.tum.www1.orion.build.OrionLocalRunConfigurationSettingsFactory
import de.tum.www1.orion.ui.util.notify
import de.tum.www1.orion.util.OrionAssessmentUtils.getAssignmentOf
import de.tum.www1.orion.util.translate
Expand All @@ -34,8 +34,10 @@ object OrionJavaTutorProjectCreator {

private fun configureRunConfiguration(project: Project) {
val runConfiguration = OrionLocalRunConfigurationSettingsFactory.runConfigurationForTutor(project)
runConfiguration.storeInDotIdeaFolder()
RunManager.getInstance(project).addConfiguration(runConfiguration)
if (runConfiguration != null) {
runConfiguration.storeInDotIdeaFolder()
RunManager.getInstance(project).addConfiguration(runConfiguration)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,11 @@ private void initState() {
}

private Map<Long, String> selectMap(ExerciseView view) {
switch (view) {
case STUDENT:
return myState.studentImports;
case TUTOR:
return myState.tutorImports;
case INSTRUCTOR:
return myState.instructorImports;
default:
throw new IllegalStateException("Data requested for non-existing exercise view " + view);
}
return switch (view) {
case STUDENT -> myState.studentImports;
case TUTOR -> myState.tutorImports;
case INSTRUCTOR -> myState.instructorImports;
};
}

public void relinkExercise(long id, ExerciseView view, @SystemIndependent String path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,13 @@ class OrionProjectRegistryStateService(private val myProject: Project) :
}
}

/**
* Suggests SDK to use for the freshly opened project.
*/
private fun State.guessProjectSdk() {
val availableSdks: List<Sdk> = when (this.language) {
ProgrammingLanguage.JAVA -> ProjectJdkTable.getInstance().allJdks.toList()
ProgrammingLanguage.KOTLIN -> ProjectJdkTable.getInstance().allJdks.toList()
ProgrammingLanguage.PYTHON -> PythonSdkUtil.getAllSdks()
else -> return
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/tum/www1/orion/ui/OrionRouterService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class OrionRouterService(private val project: Project) : OrionRouter {
}

override fun routeForDocumentation(): String {
return "https://artemis-platform.readthedocs.io/en/latest/user/orion"
return "https://docs.artemis.cit.tum.de/user/orion"
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ class OrionAssessmentEditor(
private val relativePath: String,
private val file: VirtualFile
) : FileEditorBase() {
private val headerLabel: JLabel
private val headerLabel: JLabel = createHeader(translate("orion.exercise.assessmentModeLoading").uppercase())

init {
headerLabel = createHeader(translate("orion.exercise.assessmentModeLoading").uppercase())
myEditor.headerComponent = headerLabel

initializeFeedback()
Expand Down
Loading