Skip to content

Commit

Permalink
Merge pull request #89 from JetBrains-Research/refactoring-course
Browse files Browse the repository at this point in the history
Refactoring Scenario
  • Loading branch information
mikrise2 authored Dec 18, 2023
2 parents 19f4caf + 79f433f commit ce22d0c
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kotlinx.serialization.Serializable
import org.jetbrains.research.tasktracker.config.BaseConfig
import org.jetbrains.research.tasktracker.config.YamlConfigLoadStrategy
import org.jetbrains.research.tasktracker.config.content.task.ProgrammingTask
import org.jetbrains.research.tasktracker.config.content.task.base.TaskFileInfo
import org.jetbrains.research.tasktracker.handler.content.TaskContentHandler
import java.io.File

Expand All @@ -24,16 +25,19 @@ data class TaskContentConfig(val tasks: List<ProgrammingTask>) : BaseConfig {

fun buildConfig(configFile: File): TaskContentConfig {
val config = YamlConfigLoadStrategy.load(configFile.readText(), serializer())
config.tasks.forEach { t ->
t.language?.let {
t.files.forEach { f ->
f.extension = it
f.relativePath = "${t.name}/${f.relativePath}"
f.content = f.gatherContent()
config.tasks.forEach { task ->
task.language?.let {
task.files.forEach { fileInfo ->
fileInfo.extension = it
fileInfo.relativePath = getRelativePath(task, fileInfo)
fileInfo.content = fileInfo.gatherContent()
}
}
}
return config
}

private fun getRelativePath(task: ProgrammingTask, fileInfo: TaskFileInfo) =
"${if (fileInfo.isInternal) "${task.name}/" else ""}${fileInfo.relativePath}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ interface ITaskFileInfo {
* id is intended for quick access to the corresponding VirtualFile.
*/
val id: String?

/**
* If file is default then it will be created in plugin directory and will be filled by the default code.
*
* @return true if the file needs to be created in plugin directory, false otherwise.
*/
val isInternal: Boolean
}

@Serializable
Expand All @@ -47,6 +54,7 @@ data class TaskFileInfo(override val filename: String, override val sourceSet: S
// TODO: can we avoid using var here?
override var content: String? = gatherContent()
override val id: String? = null
override val isInternal: Boolean = true

fun gatherContent() = extension?.let {
templateFile?.getTemplate(relativePath, it) ?: DefaultContentProvider.getDefaultContent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ object TaskFileHandler {
val files = task.files.map { taskFile ->
val path = getPath(project, taskFile, task)
val file = File(path)
file.writeDefaultContent(taskFile, task.name)
if (!file.exists()) {
file.writeDefaultContent(taskFile, task.name)
}
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)?.also {
taskFile.id?.let { id ->
projectTaskIdToFile[project]?.get(task)?.putIfAbsent(id, it)
Expand All @@ -108,7 +110,7 @@ object TaskFileHandler {

private fun addSourceFolders(project: Project, task: TaskWithFiles) {
val sourceFolders = task.files.map { Pair(it.extension, it.sourceSet) }.toSet().map {
"$PLUGIN_NAME/${it.first?.getFolderName()}/${task.root.pathOrEmpty()}/${it.second.path}"
"$PLUGIN_NAME/${it.first?.getDirectoryName()}/${task.root.pathOrEmpty()}/${it.second.path}"
}
sourceFolders.forEach {
ApplicationManager.getApplication().runWriteAction {
Expand All @@ -132,8 +134,11 @@ object TaskFileHandler {
}

private fun getPath(project: Project, taskFile: ITaskFileInfo, task: TaskWithFiles): String = buildString {
append("${project.basePath}/$PLUGIN_NAME/${taskFile.extension?.getFolderName() ?: ""}")
append("${task.root.pathOrEmpty()}/${taskFile.sourceSet.path}")
append("${project.basePath}/")
if (taskFile.isInternal) {
append("$PLUGIN_NAME/${taskFile.extension?.getDirectoryName() ?: ""}")
append("${task.root.pathOrEmpty()}/${taskFile.sourceSet.path}")
}
append("${taskFile.relativePath.toPackageName().pathOrEmpty()}/")
append("${taskFile.filename}${taskFile.extension?.ext ?: ""}")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ import java.util.*
fun String.toPackageName() =
listOf(" ", "-", "_").fold(this) { acc, s -> acc.replace(s, "") }.lowercase(Locale.getDefault())

fun Extension.getFolderName() = this.name.lowercase(Locale.getDefault())
fun Extension.getDirectoryName() = this.name.lowercase(Locale.getDefault())
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
text: " We’ve turned off all tracking.
text: "Thank you for taking part in our research. We’ve turned off all tracking.
If you wish, you can remove the plugin at any time from the plugins section in the IDE settings."
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pluginName: TaskTracker
pluginDescription: "TaskTracker is a plugin designed to track code changes during programming problem-solving. It monitors the modifications made to the code throughout the process of problem resolution."
pluginName: Refactoring course
pluginDescription: "We want to track your progress through the code refactoring course in order to collect data on file changes during the course completion. Please, when you are ready, press the next button."
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,4 @@ scenario:
steps:
- units:
- !<Task>
id: "hello"
- !<Survey>
id: "default"
mode: SHUFFLED
ideConfig:
settingsConfig:
theme: LIGHT
inspectionConfig:
mode: DISABLE_SELECTED
inspectionNames:
- "EmptyFinallyBlock"
- units:
- !<Setting>
mainIdeConfig:
settingsConfig:
enableCodeCompletion: OFF
- !<List>
taskIds:
- "hello"
- "example"
- units:
- !<SingleList>
taskIds:
- "hello"
- "example"
- "style"
- !<External>
url: "https://github.com/JetBrains-Research/tasktracker-3"
id: "main"
Original file line number Diff line number Diff line change
@@ -1,37 +1,162 @@
tasks:
- name: hello world
description: Write a program that will print 'hello world' to the console.
- name: Refactoring course
description: "Take the refactoring course, and after that, press the next button."
language: "KOTLIN"
focusFileId: "main"
files:
- filename: main
sourceSet: "SRC"
id: "main"
id: "hello"
- name: "Example with several files"
description: "In this task, we kindly request you to review three provided files and determine which one is the most readable and which one is the least readable. Files: [a.java](a), [b.java](b), [c.java](c)"
language: "JAVA"
id: "example"
files:
- filename: a
sourceSet: "SRC"
templateFile: "a"
id: "a"
- filename: b
sourceSet: "SRC"
templateFile: "b"
id: "b"
- filename: c
sourceSet: "SRC"
templateFile: "c"
id: "c"
- name: "python style checker"
description: "Modify the file to be more readable and compliant with PEP 8"
language: "PYTHON"
id: "style"
focusFileId: "main"
files:
- filename: "main"
- filename: "Task"
relativePath: "RefactoringAndItsPurpose/Practice/RefactoringAndItsPurposePractice/src/main/kotlin/jetbrains/refactoring/course/refactoring/purpose"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "CodeStyleAndFormatting/WhatIsFormatting/ReformatTheCode/src/main/kotlin/jetbrains/refactoring/course/formatting"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "CodeStyleAndFormatting/WhatIsFormatting/ReformatTheCodeUsingIDE/src/main/kotlin/jetbrains/refactoring/course/formatting"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "CodeStyleAndFormatting/CodeSchemasAndEditorConfig/task/src/main/kotlin/jetbrains/refactoring/course/formatting"
sourceSet: "SRC"
isInternal: false
- filename: ".editorconfig"
relativePath: "CodeStyleAndFormatting/CodeSchemasAndEditorConfig/task"
sourceSet: "SRC"
isInternal: false
- filename: "Student"
relativePath: "RenamingCode/RenameRefactoringInIDE/FixTypos/src/main/kotlin/jetbrains/refactoring/course/renaming"
sourceSet: "SRC"
isInternal: false
- filename: "University"
relativePath: "RenamingCode/RenameRefactoringInIDE/FixTypos/src/main/kotlin/jetbrains/refactoring/course/renaming"
sourceSet: "SRC"
isInternal: false
- filename: "Main"
relativePath: "MovingCode/WhatIsMoveMethodRefactoring/task/src/main/kotlin/jetbrains/refactoring/course/moving"
sourceSet: "SRC"
isInternal: false
- filename: "Driver"
relativePath: "MovingCode/WhatIsMoveMethodRefactoring/task/src/main/kotlin/jetbrains/refactoring/course/moving/driver"
sourceSet: "SRC"
isInternal: false
- filename: "Car"
relativePath: "MovingCode/WhatIsMoveMethodRefactoring/task/src/main/kotlin/jetbrains/refactoring/course/moving/car"
sourceSet: "SRC"
isInternal: false
- filename: "Animal"
relativePath: "MovingCode/WhatArePullUpAndPushDownRefactorings/task/src/main/kotlin/jetbrains/refactoring/course/moving"
sourceSet: "SRC"
isInternal: false
- filename: "Cat"
relativePath: "MovingCode/WhatArePullUpAndPushDownRefactorings/task/src/main/kotlin/jetbrains/refactoring/course/moving"
sourceSet: "SRC"
isInternal: false
- filename: "Dog"
relativePath: "MovingCode/WhatArePullUpAndPushDownRefactorings/task/src/main/kotlin/jetbrains/refactoring/course/moving"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "ExtractingCode/WhatIsExtractMethodRefactoring/ExtractDuplicatedCode/src/main/kotlin/jetbrains/refactoring/course/extracting"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "ExtractingCode/WhatIsExtractVariableRefactoring/ExtractMagicConstants/src/main/kotlin/jetbrains/refactoring/course/extracting"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "InliningCode/WhatIsInlineVariableRefactoring/InlineVariables/src/main/kotlin/jetbrains/refactoring/course/inlining"
sourceSet: "SRC"
isInternal: false
- filename: "Task"
relativePath: "InliningCode/InlineMethodRefactoring/InlineMethodAndVariables/src/main/kotlin/jetbrains/refactoring/course/inlining"
sourceSet: "SRC"
isInternal: false
- filename: "MiddleMan"
relativePath: "InliningCode/MiddleManCodeSmell/task/src/main/kotlin/jetbrains/refactoring/course/inlining"
sourceSet: "SRC"
isInternal: false
- filename: "Main"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "VideoConversionFacade"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "VideoEncoder"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "VideoLoader"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "VideoProcessor"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "VideoSaver"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "EncodedVideo"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/video"
sourceSet: "SRC"
isInternal: false
- filename: "ProcessedVideo"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/video"
sourceSet: "SRC"
isInternal: false
- filename: "Video"
relativePath: "RefactoringToDesignPatterns/FacadePatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/video"
sourceSet: "SRC"
isInternal: false
- filename: "Main"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "Order"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "PaymentProcessor"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/processor"
sourceSet: "SRC"
isInternal: false
- filename: "BitcoinPayment"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/strategy"
sourceSet: "SRC"
isInternal: false
- filename: "CreditCardPayment"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/strategy"
sourceSet: "SRC"
isInternal: false
- filename: "PaymentStrategy"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/strategy"
sourceSet: "SRC"
isInternal: false
- filename: "PayPalPayment"
relativePath: "RefactoringToDesignPatterns/StrategyPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns/strategy"
sourceSet: "SRC"
isInternal: false
- filename: "Bicycle"
relativePath: "RefactoringToDesignPatterns/FactoryMethodPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "Car"
relativePath: "RefactoringToDesignPatterns/FactoryMethodPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "Main"
relativePath: "RefactoringToDesignPatterns/FactoryMethodPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "Transport"
relativePath: "RefactoringToDesignPatterns/FactoryMethodPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
isInternal: false
- filename: "TransportationServiceFactory"
relativePath: "RefactoringToDesignPatterns/FactoryMethodPatternPractice/task/src/main/kotlin/jetbrains/refactoring/course/patterns"
sourceSet: "SRC"
templateFile: "comparison"
id: "main"
isInternal: false
id: "main"
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ data class MockTaskFile(
override val templateFile: String? = null,
) : ITaskFileInfo {
override val sourceSet: SourceSet = SourceSet.SRC
override val isInternal: Boolean
get() = true
}

fun List<VirtualFile>.toMockTask(project: Project): MockTask {
Expand Down

0 comments on commit ce22d0c

Please sign in to comment.