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

Refactoring Scenario #89

Merged
merged 1 commit into from
Dec 18, 2023
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
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"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be very helpful to have utils to generate this file by a course automatically

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or put the whole folder and add all files from this folder, what do you think?

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
Loading