Skip to content

Commit e611e47

Browse files
rudolf101zishkaz
andauthored
Fix activation of UTBot action for JavaScript files (#1901)
Co-authored-by: Sergey Loktev <loktevsergay.2003@gmail.com>
1 parent 5db82b4 commit e611e47

File tree

2 files changed

+64
-51
lines changed

2 files changed

+64
-51
lines changed

utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsDialogProcessor.kt

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ object JsDialogProcessor {
4646
fileMethods: Set<JSMemberInfo>,
4747
focusedMethod: JSMemberInfo?,
4848
containingFilePath: String,
49-
editor: Editor,
49+
editor: Editor?,
5050
file: JSFile
5151
) {
5252
val model =
@@ -64,12 +64,19 @@ object JsDialogProcessor {
6464
createDialog(model)?.let { dialogWindow ->
6565
if (!dialogWindow.showAndGet()) return@invokeLater
6666
// Since Tern.js accesses containing file, sync with file system required before test generation.
67-
runWriteAction {
68-
with(FileDocumentManager.getInstance()) {
69-
saveDocument(editor.document)
67+
editor?.let {
68+
runWriteAction {
69+
with(FileDocumentManager.getInstance()) {
70+
saveDocument(editor.document)
71+
}
7072
}
7173
}
72-
createTests(dialogWindow.model, containingFilePath, editor)
74+
createTests(
75+
dialogWindow.model,
76+
containingFilePath,
77+
editor,
78+
dialogWindow.model.file.getContent()
79+
)
7380
}
7481
}
7582
}
@@ -137,14 +144,7 @@ object JsDialogProcessor {
137144

138145
private fun createDialog(jsTestsModel: JsTestsModel?) = jsTestsModel?.let { JsDialogWindow(it) }
139146

140-
private fun unblockDocument(project: Project, document: Document) {
141-
PsiDocumentManager.getInstance(project).apply {
142-
commitDocument(document)
143-
doPostponedOperationsAndUnblockDocument(document)
144-
}
145-
}
146-
147-
private fun createTests(model: JsTestsModel, containingFilePath: String, editor: Editor) {
147+
private fun createTests(model: JsTestsModel, containingFilePath: String, editor: Editor?, contents: String) {
148148
val normalizedContainingFilePath = containingFilePath.replace(File.separator, "/")
149149
(object : Task.Backgroundable(model.project, "Generate tests") {
150150
override fun run(indicator: ProgressIndicator) {
@@ -154,7 +154,7 @@ object JsDialogProcessor {
154154
model.testSourceRoot!!
155155
)
156156
val testFileName = normalizedContainingFilePath.substringAfterLast("/").replace(Regex(".js"), "Test.js")
157-
val testGenerator = JsTestGenerator(fileText = editor.document.text,
157+
val testGenerator = JsTestGenerator(fileText = contents,
158158
sourceFilePath = normalizedContainingFilePath,
159159
projectPath = model.project.basePath?.replace(File.separator, "/")
160160
?: throw IllegalStateException("Can't access project path."),
@@ -168,28 +168,27 @@ object JsDialogProcessor {
168168
if (name == dummyClassName) null else name
169169
},
170170
outputFilePath = "${testDir.virtualFile.path}/$testFileName".replace(File.separator, "/"),
171-
exportsManager = partialApplication(JsDialogProcessor::manageExports, editor, project),
171+
exportsManager = partialApplication(
172+
JsDialogProcessor::manageExports, editor, project, model
173+
),
172174
settings = JsDynamicSettings(
173175
pathToNode = model.pathToNode,
174176
pathToNYC = model.pathToNYC,
175177
pathToNPM = model.pathToNPM,
176178
timeout = model.timeout,
177179
coverageMode = model.coverageMode
178180
),
179-
isCancelled = { indicator.isCanceled }
180-
)
181+
isCancelled = { indicator.isCanceled })
181182

182183
indicator.fraction = indicator.fraction.coerceAtLeast(0.9)
183184
indicator.text = "Generate code for tests"
184185

185186
val generatedCode = testGenerator.run()
186187
invokeLater {
187188
runWriteAction {
188-
val testPsiFile =
189-
testDir.findFile(testFileName) ?: PsiFileFactory.getInstance(project)
190-
.createFileFromText(testFileName, JsLanguageAssistant.jsLanguage, generatedCode)
191-
val testFileEditor =
192-
CodeInsightUtil.positionCursor(project, testPsiFile, testPsiFile)
189+
val testPsiFile = testDir.findFile(testFileName) ?: PsiFileFactory.getInstance(project)
190+
.createFileFromText(testFileName, JsLanguageAssistant.jsLanguage, generatedCode)
191+
val testFileEditor = CodeInsightUtil.positionCursor(project, testPsiFile, testPsiFile)
193192
unblockDocument(project, testFileEditor.document)
194193
testFileEditor.document.setText(generatedCode)
195194
unblockDocument(project, testFileEditor.document)
@@ -200,15 +199,19 @@ object JsDialogProcessor {
200199
}).queue()
201200
}
202201

203-
private fun <A, B, C> partialApplication(f: (A, B, C) -> Unit, a: A, b: B): (C) -> Unit {
204-
return { c: C -> f(a, b, c) }
202+
private fun <A, B, C, D> partialApplication(f: (A, B, C, D) -> Unit, a: A, b: B, c: C): (D) -> Unit {
203+
return { d: D -> f(a, b, c, d) }
205204
}
206205

207-
private fun manageExports(editor: Editor, project: Project, exports: List<String>) {
206+
private fun JSFile.getContent(): String = this.viewProvider.contents.toString()
207+
208+
private fun manageExports(
209+
editor: Editor?, project: Project, model: JsTestsModel, exports: List<String>
210+
) {
208211
AppExecutorUtil.getAppExecutorService().submit {
209212
invokeLater {
210213
val exportSection = exports.joinToString("\n") { "exports.$it = $it" }
211-
val fileText = editor.document.text
214+
val fileText = model.file.getContent()
212215
when {
213216
fileText.contains(exportSection) -> {}
214217

@@ -223,16 +226,7 @@ object JsDialogProcessor {
223226
val resultSet = existingExportsSet + exports.toSet()
224227
val resSection = resultSet.joinToString("\n") { "exports.$it = $it" }
225228
val swappedText = fileText.replace(existingSection, "\n$resSection\n")
226-
runWriteAction {
227-
with(editor.document) {
228-
unblockDocument(project, this)
229-
setText(swappedText)
230-
unblockDocument(project, this)
231-
}
232-
with(FileDocumentManager.getInstance()) {
233-
saveDocument(editor.document)
234-
}
235-
}
229+
project.setNewText(editor, model.containingFilePath, swappedText)
236230
}
237231
}
238232

@@ -242,21 +236,36 @@ object JsDialogProcessor {
242236
append(exportSection)
243237
append("\n$endComment")
244238
}
245-
runWriteAction {
246-
with(editor.document) {
247-
unblockDocument(project, this)
248-
setText(fileText + line)
249-
unblockDocument(project, this)
250-
}
251-
with(FileDocumentManager.getInstance()) {
252-
saveDocument(editor.document)
253-
}
254-
}
239+
project.setNewText(editor, model.containingFilePath, fileText + line)
255240
}
256241
}
257242
}
258243
}
259244
}
245+
246+
private fun Project.setNewText(editor: Editor?, filePath: String, text: String) {
247+
editor?.let {
248+
runWriteAction {
249+
with(editor.document) {
250+
unblockDocument(this@setNewText, this@with)
251+
setText(text)
252+
unblockDocument(this@setNewText, this@with)
253+
}
254+
with(FileDocumentManager.getInstance()) {
255+
saveDocument(editor.document)
256+
}
257+
}
258+
} ?: run {
259+
File(filePath).writeText(text)
260+
}
261+
}
262+
263+
private fun unblockDocument(project: Project, document: Document) {
264+
PsiDocumentManager.getInstance(project).apply {
265+
commitDocument(document)
266+
doPostponedOperationsAndUnblockDocument(document)
267+
}
268+
}
260269
}
261270

262271
private fun PackageDataService.checkAndInstallRequirements(project: Project): Boolean {

utbot-intellij-js/src/main/kotlin/org/utbot/intellij/plugin/language/js/JsLanguageAssistant.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ object JsLanguageAssistant : LanguageAssistant() {
2929
val focusedMethod: JSMemberInfo?,
3030
val module: Module,
3131
val containingFilePath: String,
32-
val editor: Editor,
32+
val editor: Editor?,
3333
val file: JSFile
3434
)
3535

@@ -53,11 +53,15 @@ object JsLanguageAssistant : LanguageAssistant() {
5353

5454
private fun getPsiTargets(e: AnActionEvent): PsiTargets? {
5555
e.project ?: return null
56-
val virtualFile = (e.getData(CommonDataKeys.VIRTUAL_FILE) ?: return null).path
57-
val editor = e.getData(CommonDataKeys.EDITOR) ?: return null
56+
val editor = e.getData(CommonDataKeys.EDITOR)
5857
val file = e.getData(CommonDataKeys.PSI_FILE) as? JSFile ?: return null
59-
val element = findPsiElement(file, editor) ?: return null
58+
val element = if (editor != null) {
59+
findPsiElement(file, editor) ?: return null
60+
} else {
61+
e.getData(CommonDataKeys.PSI_ELEMENT) ?: return null
62+
}
6063
val module = element.module ?: return null
64+
val virtualFile = (e.getData(CommonDataKeys.VIRTUAL_FILE) ?: return null).path
6165
val focusedMethod = getContainingMethod(element)
6266
containingClass(element)?.let {
6367
val methods = it.functions
@@ -143,4 +147,4 @@ object JsLanguageAssistant : LanguageAssistant() {
143147
JSMemberInfo.extractClassMembers(clazz!!, res) { true }
144148
return res.toSet()
145149
}
146-
}
150+
}

0 commit comments

Comments
 (0)