-
Notifications
You must be signed in to change notification settings - Fork 7
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
Features/#277 create missing env file #445
Merged
Merged
Changes from 7 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
128c924
Quickfix was implemented.
5b0c244
Exceptions handling was implemented.
8cf1859
Smart file path collecting. CHANGELOG was updated.
037cd71
Minor changes in messages and 'CrateMissedFile' behaviour. 'UndoableA…
2d6f1e2
Merge branch 'master' of https://github.com/JetBrains-Research/snakec…
088bdbc
Quick fix now available for the following sections: conda, notebook, …
754511f
Fix in extension behaviour.
c4d4a35
Minor fix in tests. Maybe asynchronous creation of file somehow affec…
ed06af7
Cosmetics.
603b190
Fix for absolute path, error message fix, logging was added, VFS api …
b883378
Now files aren't created in the UI thread.
a2baf11
Merge branch 'master' into features/#277-create-missing-env-file
dakochik 0521695
refactor: one long method split in several short
iromeo 304a448
refactor: CreateMissedFile quickfix split in 2 classes
iromeo acbbf59
fix: refresh only one VFS folder + do it async
iromeo b4eee94
fix: sometimes VFS refresh doesn't see FS changes due to some FS lag,…
iromeo 2e9e433
refactor: comments updated
iromeo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
.../kotlin/com/jetbrains/snakecharm/inspections/SmkUnresolvedReferenceInspectionExtension.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.jetbrains.snakecharm.inspections | ||
|
||
import com.intellij.codeInspection.LocalQuickFix | ||
import com.intellij.psi.* | ||
import com.jetbrains.python.inspections.PyUnresolvedReferenceQuickFixProvider | ||
import com.jetbrains.snakecharm.inspections.quickfix.CreateMissedFile | ||
import com.jetbrains.snakecharm.lang.psi.SmkArgsSection | ||
import com.jetbrains.snakecharm.lang.psi.SmkFileReference | ||
|
||
class SmkUnresolvedReferenceInspectionExtension : PyUnresolvedReferenceQuickFixProvider { | ||
|
||
override fun registerQuickFixes(reference: PsiReference, existing: MutableList<LocalQuickFix>) { | ||
val section = reference.element as? SmkArgsSection ?: return | ||
val sectionName = section.sectionKeyword ?: return | ||
if (CreateMissedFile.supportedSections.containsKey(sectionName)) { | ||
val fileReference = (section.reference as? SmkFileReference) ?: return | ||
if (!fileReference.hasAppropriateSuffix()) { | ||
return | ||
} | ||
val name = fileReference.path | ||
existing.add(CreateMissedFile(section, name, sectionName, fileReference.searchRelativelyToCurrentFolder)) | ||
} | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
src/main/kotlin/com/jetbrains/snakecharm/inspections/quickfix/CreateMissedFile.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package com.jetbrains.snakecharm.inspections.quickfix | ||
|
||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement | ||
import com.intellij.openapi.application.ApplicationManager | ||
import com.intellij.openapi.application.ModalityState | ||
import com.intellij.openapi.command.undo.* | ||
import com.intellij.openapi.editor.Editor | ||
import com.intellij.openapi.project.Project | ||
import com.intellij.openapi.roots.ProjectRootManager | ||
import com.intellij.openapi.vfs.LocalFileSystem | ||
import com.intellij.openapi.vfs.VfsUtil | ||
import com.intellij.openapi.vfs.VirtualFileManager | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
import com.jetbrains.snakecharm.SmkNotifier | ||
import com.jetbrains.snakecharm.SnakemakeBundle | ||
import com.jetbrains.snakecharm.lang.SnakemakeNames | ||
import org.apache.commons.io.FileUtils | ||
import java.io.IOException | ||
import java.nio.file.Files | ||
import java.nio.file.Paths | ||
import kotlin.io.path.isDirectory | ||
import kotlin.io.path.name | ||
import kotlin.io.path.notExists | ||
|
||
class CreateMissedFile( | ||
element: PsiElement, | ||
private val fileName: String, | ||
private val sectionName: String, | ||
private val searchRelativelyToCurrentFolder: Boolean | ||
) : LocalQuickFixAndIntentionActionOnPsiElement(element) { | ||
companion object { | ||
private val condaDefaultContext = """ | ||
channels: | ||
dependencies: | ||
""".trimIndent() | ||
|
||
// Update it if wee need default text | ||
val supportedSections = mapOf( | ||
SnakemakeNames.SECTION_CONDA to condaDefaultContext, | ||
SnakemakeNames.SECTION_NOTEBOOK to null, | ||
SnakemakeNames.SECTION_SCRIPT to null, | ||
SnakemakeNames.MODULE_SNAKEFILE_KEYWORD to null, | ||
|
||
SnakemakeNames.WORKFLOW_CONFIGFILE_KEYWORD to null, | ||
SnakemakeNames.WORKFLOW_PEPFILE_KEYWORD to null, | ||
SnakemakeNames.WORKFLOW_PEPSCHEMA_KEYWORD to null | ||
) | ||
} | ||
|
||
override fun getFamilyName() = SnakemakeBundle.message("INSP.NAME.conda.env.missing.fix", fileName) | ||
|
||
override fun getText() = familyName | ||
|
||
override fun invoke( | ||
project: Project, | ||
file: PsiFile, | ||
editor: Editor?, | ||
startElement: PsiElement, | ||
endElement: PsiElement | ||
) { | ||
val dir = | ||
if (searchRelativelyToCurrentFolder) file.virtualFile.parent else ProjectRootManager.getInstance(project).fileIndex.getContentRootForFile( | ||
file.virtualFile | ||
) ?: return | ||
val targetFilePath = Paths.get(dir.path, fileName) | ||
var firstAffectedFile = targetFilePath | ||
while (firstAffectedFile.parent.notExists()) { | ||
firstAffectedFile = firstAffectedFile.parent ?: break | ||
} | ||
|
||
val undo = Runnable { | ||
firstAffectedFile ?: return@Runnable | ||
if (firstAffectedFile.isDirectory()) { | ||
FileUtils.deleteDirectory(firstAffectedFile.toFile()) | ||
} else { | ||
Files.delete(firstAffectedFile) | ||
} | ||
VirtualFileManager.getInstance().asyncRefresh { } | ||
} | ||
val redo = Runnable { | ||
if (!supportedSections.containsKey(sectionName)) { | ||
return@Runnable | ||
} | ||
try { | ||
val directoryPath = Files.createDirectories(targetFilePath.parent) | ||
val directoryVirtualFile = VfsUtil.findFile(directoryPath, true) ?: return@Runnable | ||
LocalFileSystem.getInstance().createChildFile(this, directoryVirtualFile, targetFilePath.name) | ||
VirtualFileManager.getInstance().asyncRefresh { } | ||
val context = supportedSections[sectionName] | ||
if (context != null) { | ||
// We don't use the result of 'createChildFile()' because it has inappropriate type (and throw UnsupportedOperationException) | ||
targetFilePath.toFile().appendText(context) | ||
} | ||
} catch (e: SecurityException) { | ||
SmkNotifier.notifyTargetFileIsInvalid(fileName, project) | ||
} catch (e: IOException) { | ||
SmkNotifier.notifyImpossibleToCreateFileOrDirectory(fileName, project) | ||
} | ||
} | ||
val action = object : UndoableAction { | ||
override fun undo() { | ||
// invoke later because changing document inside undo/redo is not allowed (see ChangeFileEncodingAction) | ||
ApplicationManager.getApplication().invokeLater(undo, ModalityState.NON_MODAL, project.disposed) | ||
} | ||
|
||
override fun redo() { | ||
// invoke later because changing document inside undo/redo is not allowed (see ChangeFileEncodingAction) | ||
ApplicationManager.getApplication().invokeLater(redo, ModalityState.NON_MODAL, project.disposed) | ||
} | ||
|
||
override fun getAffectedDocuments(): Array<DocumentReference> = | ||
arrayOf(DocumentReferenceManager.getInstance().create(file.virtualFile)) | ||
|
||
override fun isGlobal() = true | ||
} | ||
action.redo() | ||
UndoManager.getInstance(project).undoableActionPerformed(action) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
src/test/resources/features/highlighting/inspections/unresolved_reference_extension.feature
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Feature: Inspection: SmkUnresolvedReferenceInspectionExtension | ||
|
||
Scenario Outline: Quick fix fot missed files | ||
Given a snakemake project | ||
Given I open a file "foo.smk" with text | ||
""" | ||
<section>: "<path>" | ||
""" | ||
And PyUnresolvedReferencesInspection inspection is enabled | ||
Then I expect inspection error on <<path>> with message | ||
""" | ||
Unresolved reference '<path>' | ||
""" | ||
When I check highlighting warnings | ||
And I invoke quick fix Create '<path>' and see text: | ||
""" | ||
<section>: "<path>" | ||
""" | ||
Examples: | ||
| path | section | | ||
| NAME.yaml | rule NAME: conda | | ||
| envs/NAME.yaml | rule NAME: conda | | ||
| ../envs/NAME.yaml | rule NAME: conda | | ||
| NAME.py.ipynb | rule NAME: notebook | | ||
| NAME.py | rule NAME: script | | ||
| boo.smk | module NAME: snakefile | | ||
| NAME.yaml | configfile | | ||
| NAME.yaml | pepfile | | ||
| NAME.yml | pepschema | | ||
|
||
# Impossible to check whether the file has been created because: | ||
# 1) It is being creating asynchronously | ||
# 2) So, we may need async refresh() (see LightTempDirTestFixtureImpl.java:137) | ||
# It leads to Exception: "Do not perform a synchronous refresh under read lock ..." |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What for do we need refresh here? And why async? Is it a workaround to resart inspections in the current file? According to source code com.intellij.openapi.vfs.impl.local.LocalFileSystemBase.createChildFile does some events publishing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, not sure that we need to interact with Virtual File System here. 'undo' uses just "java.io.File" standard Java SDK API. Here maybe is better to check existence/create file w/o using VFS api, refresing, etc.