@@ -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
262271private fun PackageDataService.checkAndInstallRequirements (project : Project ): Boolean {
0 commit comments