24
24
25
25
public class CsvPsiTreeUpdater implements PsiFileHolder , Suspendable {
26
26
27
- private final PsiFileHolder myPsiFileHolder ;
27
+ protected final EventListenerList myEventListenerList = new EventListenerList () ;
28
28
29
- private final PsiFileFactory myFileFactory ;
29
+ private final PsiFileHolder myPsiFileHolder ;
30
30
31
- private final CsvPsiParserFileType myFileType ;
31
+ private PsiFileFactory myFileFactory ;
32
32
33
- protected final EventListenerList myEventListenerList = new EventListenerList () ;
33
+ private CsvPsiParserFileType myFileType ;
34
34
35
35
private List <PsiAction > myUncommittedActions = new ArrayList <>();
36
36
37
37
public CsvPsiTreeUpdater (@ NotNull PsiFileHolder psiFileHolder ) {
38
38
myPsiFileHolder = psiFileHolder ;
39
- myFileFactory = PsiFileFactory .getInstance (getPsiFile ().getProject ());
40
- myFileType = new CsvPsiParserFileType (CsvHelper .getValueSeparator (psiFileHolder .getPsiFile ()), CsvHelper .getEscapeCharacter (psiFileHolder .getPsiFile ()));
41
39
}
42
40
43
41
private FileType getFileType () {
44
- myFileType .setSeparator (CsvHelper .getValueSeparator (getPsiFile ()));
45
- myFileType .setEscapeCharacter (CsvHelper .getEscapeCharacter (getPsiFile ()));
42
+ PsiFile psiFile = getPsiFile ();
43
+ if (psiFile == null ) return null ;
44
+
45
+ if (myFileType == null ) {
46
+ myFileType = new CsvPsiParserFileType (CsvHelper .getValueSeparator (psiFile ), CsvHelper .getEscapeCharacter (psiFile ));
47
+ } else {
48
+ myFileType .setSeparator (CsvHelper .getValueSeparator (psiFile ));
49
+ myFileType .setEscapeCharacter (CsvHelper .getEscapeCharacter (psiFile ));
50
+ }
46
51
return myFileType ;
47
52
}
48
53
54
+ private PsiFileFactory getFileFactory () {
55
+ PsiFile psiFile = getPsiFile ();
56
+ if (psiFile == null ) return null ;
57
+
58
+ if (myFileFactory == null ) {
59
+ myFileFactory = PsiFileFactory .getInstance (getPsiFile ().getProject ());
60
+ }
61
+ return myFileFactory ;
62
+ }
63
+
49
64
private PsiFile createFile (@ NotNull String text ) {
50
- return myFileFactory .createFileFromText ("a.csv" , getFileType (), text );
65
+ PsiFileFactory fileFactory = getFileFactory ();
66
+ return fileFactory == null ? null : getFileFactory ().createFileFromText ("a.csv" , getFileType (), text );
51
67
}
52
68
53
69
private boolean isIndicatingComment (@ NotNull String text ) {
@@ -63,7 +79,7 @@ private boolean isIndicatingComment(@NotNull String text) {
63
79
return SyntaxTraverser .psiTraverser (createFile (sanitizedValue )).filter (CsvField .class ).first ();
64
80
}
65
81
66
- public @ NotNull CsvRecord createRecord () {
82
+ public @ Nullable CsvRecord createRecord () {
67
83
return SyntaxTraverser .psiTraverser (createFile ("\n " )).filter (CsvRecord .class ).first ();
68
84
}
69
85
@@ -73,6 +89,8 @@ private boolean isIndicatingComment(@NotNull String text) {
73
89
74
90
public Document getDocument () {
75
91
PsiFile psiFile = getPsiFile ();
92
+ if (psiFile == null ) return null ;
93
+
76
94
return PsiDocumentManager .getInstance (psiFile .getProject ()).getDocument (psiFile );
77
95
}
78
96
@@ -244,12 +262,16 @@ public void deleteRow(@NotNull PsiElement row) {
244
262
}
245
263
246
264
public void deleteRows (Collection <Integer > indices ) {
247
- Set <PsiElement > toDelete = new HashSet <>();
248
265
PsiFile psiFile = getPsiFile ();
266
+ if (psiFile == null ) return ;
267
+
268
+ Set <PsiElement > toDelete = new HashSet <>();
249
269
List <Integer > sortedIndices = new ArrayList <>(indices );
250
270
Collections .sort (sortedIndices );
251
271
for (int rowIndex : sortedIndices ) {
252
272
CsvRecord row = PsiHelper .getNthChildOfType (psiFile , rowIndex , CsvRecord .class );
273
+ if (row == null ) continue ;
274
+
253
275
boolean removePreviousLF = rowIndex > 0 ;
254
276
PsiElement lf = PsiHelper .getSiblingOfType (row , CsvTypes .CRLF , removePreviousLF );
255
277
if (lf == null || toDelete .contains (lf )) {
@@ -318,34 +340,34 @@ private void doAddField(@NotNull PsiElement anchor, @Nullable String text, boole
318
340
public synchronized void commit () {
319
341
if (isSuspended () || myUncommittedActions == null || myUncommittedActions .size () == 0 ) return ;
320
342
321
- suspend ();
322
343
List <PsiAction > actionsToCommit = new ArrayList <>(myUncommittedActions );
323
- if (!doCommit (() -> {
324
- try {
325
- actionsToCommit .forEach (PsiAction ::execute );
326
- } finally {
327
- resume ();
328
- fireCommitted ();
329
- }
330
- })) {
331
- resume ();
332
- } else {
333
- myUncommittedActions .clear ();
334
- }
344
+ myUncommittedActions .clear ();
345
+
346
+ doCommit (() -> actionsToCommit .forEach (PsiAction ::execute ));
335
347
}
336
348
337
349
private boolean doCommit (@ NotNull Runnable runnable ) {
338
- if (!getPsiFile ().isWritable ()) return false ;
339
-
350
+ PsiFile psiFile = getPsiFile ();
340
351
Document document = getDocument ();
341
352
353
+ if (psiFile == null || !psiFile .isWritable () || document == null || !document .isWritable ())
354
+ {
355
+ return false ;
356
+ }
357
+
358
+ suspend ();
342
359
ApplicationManager .getApplication ().runWriteAction (() -> {
343
- CommandProcessor .getInstance ().executeCommand (
344
- getPsiFile ().getProject (),
345
- () -> DocumentUtil .executeInBulk (document , runnable ),
346
- "CSV Editor changes" ,
347
- null ,
348
- document );
360
+ try {
361
+ CommandProcessor .getInstance ().executeCommand (
362
+ getPsiFile ().getProject (),
363
+ () -> DocumentUtil .executeInBulk (document , runnable ),
364
+ "CSV Editor changes" ,
365
+ null ,
366
+ document );
367
+ } finally {
368
+ resume ();
369
+ fireCommitted ();
370
+ }
349
371
});
350
372
351
373
return true ;
@@ -394,18 +416,20 @@ private static class AddSiblingPsiAction extends PsiAction {
394
416
private final PsiElement myElementToAdd ;
395
417
private final boolean myBefore ;
396
418
397
- AddSiblingPsiAction (@ NotNull PsiElement anchor , @ NotNull PsiElement elementToAdd ) {
419
+ AddSiblingPsiAction (@ NotNull PsiElement anchor , @ Nullable PsiElement elementToAdd ) {
398
420
this (anchor , elementToAdd , false );
399
421
}
400
422
401
- AddSiblingPsiAction (@ NotNull PsiElement anchor , @ NotNull PsiElement elementToAdd , boolean before ) {
423
+ AddSiblingPsiAction (@ NotNull PsiElement anchor , @ Nullable PsiElement elementToAdd , boolean before ) {
402
424
super (anchor );
403
425
myElementToAdd = elementToAdd ;
404
426
myBefore = before ;
405
427
}
406
428
407
429
@ Override
408
430
public void execute () {
431
+ if (myElementToAdd == null ) return ;
432
+
409
433
PsiElement anchor = getAnchor ();
410
434
if (anchor .getParent () == null ) return ;
411
435
if (myBefore ) {
@@ -420,13 +444,15 @@ private static class AddChildPsiAction extends PsiAction {
420
444
421
445
private final PsiElement myElementToAdd ;
422
446
423
- AddChildPsiAction (@ NotNull PsiElement parent , @ NotNull PsiElement elementToAdd ) {
447
+ AddChildPsiAction (@ NotNull PsiElement parent , @ Nullable PsiElement elementToAdd ) {
424
448
super (parent );
425
449
myElementToAdd = elementToAdd ;
426
450
}
427
451
428
452
@ Override
429
453
public void execute () {
454
+ if (myElementToAdd == null ) return ;
455
+
430
456
PsiElement anchor = getAnchor ();
431
457
anchor .add (myElementToAdd );
432
458
}
@@ -436,13 +462,15 @@ private static class ReplacePsiAction extends PsiAction {
436
462
437
463
private final PsiElement myReplacement ;
438
464
439
- ReplacePsiAction (@ NotNull PsiElement anchor , @ NotNull PsiElement replacement ) {
465
+ ReplacePsiAction (@ NotNull PsiElement anchor , @ Nullable PsiElement replacement ) {
440
466
super (anchor );
441
467
myReplacement = replacement ;
442
468
}
443
469
444
470
@ Override
445
471
public void execute () {
472
+ if (myReplacement == null ) return ;
473
+
446
474
getAnchor ().replace (myReplacement );
447
475
}
448
476
}
@@ -491,6 +519,8 @@ public void execute() {
491
519
492
520
PsiDocumentManager manager = PsiDocumentManager .getInstance (psiFile .getProject ());
493
521
Document document = manager .getDocument (psiFile );
522
+ if (document == null ) return ;
523
+
494
524
manager .doPostponedOperationsAndUnblockDocument (document );
495
525
496
526
int offset = 0 ;
0 commit comments