2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com
.intellij
.codeInsight
;
19 import com
.intellij
.codeInsight
.hint
.HintManager
;
20 import com
.intellij
.lang
.Language
;
21 import com
.intellij
.openapi
.application
.ApplicationManager
;
22 import com
.intellij
.openapi
.editor
.Document
;
23 import com
.intellij
.openapi
.editor
.Editor
;
24 import com
.intellij
.openapi
.editor
.RangeMarker
;
25 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
26 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
27 import com
.intellij
.openapi
.project
.Project
;
28 import com
.intellij
.openapi
.vfs
.ReadonlyStatusHandler
;
29 import com
.intellij
.openapi
.vfs
.VfsUtil
;
30 import com
.intellij
.openapi
.vfs
.VirtualFile
;
31 import com
.intellij
.psi
.PsiDocumentManager
;
32 import com
.intellij
.psi
.PsiElement
;
33 import com
.intellij
.psi
.PsiFile
;
34 import com
.intellij
.psi
.PsiWhiteSpace
;
35 import com
.intellij
.psi
.util
.PsiTreeUtil
;
36 import com
.intellij
.psi
.util
.PsiUtilBase
;
37 import com
.intellij
.util
.ReflectionCache
;
38 import gnu
.trove
.THashSet
;
40 import java
.util
.Arrays
;
41 import java
.util
.Collection
;
44 public class CodeInsightUtilBase
{
45 private CodeInsightUtilBase() {
48 static <T
extends PsiElement
> T
findElementInRange(final PsiFile file
,
52 final Language language
) {
53 PsiElement element1
= file
.getViewProvider().findElementAt(startOffset
, language
);
54 PsiElement element2
= file
.getViewProvider().findElementAt(endOffset
- 1, language
);
55 if (element1
instanceof PsiWhiteSpace
) {
56 startOffset
= element1
.getTextRange().getEndOffset();
57 element1
= file
.getViewProvider().findElementAt(startOffset
, language
);
59 if (element2
instanceof PsiWhiteSpace
) {
60 endOffset
= element2
.getTextRange().getStartOffset();
61 element2
= file
.getViewProvider().findElementAt(endOffset
- 1, language
);
63 if (element2
== null || element1
== null) return null;
64 final PsiElement commonParent
= PsiTreeUtil
.findCommonParent(element1
, element2
);
66 ReflectionCache
.isAssignable(klass
, commonParent
.getClass())
67 ?
(T
)commonParent
: PsiTreeUtil
.getParentOfType(commonParent
, klass
);
68 if (element
== null || element
.getTextRange().getStartOffset() != startOffset
|| element
.getTextRange().getEndOffset() != endOffset
) {
74 public static <T
extends PsiElement
> T
forcePsiPostprocessAndRestoreElement(final T element
) {
75 final PsiFile psiFile
= element
.getContainingFile();
76 final Document document
= psiFile
.getViewProvider().getDocument();
77 if (document
== null) return element
;
78 final Language language
= PsiUtilBase
.getDialect(element
);
79 final PsiDocumentManager documentManager
= PsiDocumentManager
.getInstance(psiFile
.getProject());
80 final RangeMarker rangeMarker
= document
.createRangeMarker(element
.getTextRange());
81 documentManager
.doPostponedOperationsAndUnblockDocument(document
);
82 documentManager
.commitDocument(document
);
84 return findElementInRange(psiFile
, rangeMarker
.getStartOffset(), rangeMarker
.getEndOffset(),
85 (Class
<?
extends T
>)element
.getClass(),
89 public static boolean prepareFileForWrite(final PsiFile psiFile
) {
90 if (psiFile
== null) return false;
91 final VirtualFile file
= psiFile
.getVirtualFile();
92 final Project project
= psiFile
.getProject();
95 psiFile
.isWritable() ?
null : FileEditorManager
.getInstance(project
).openTextEditor(new OpenFileDescriptor(project
, file
), true);
96 if (!ReadonlyStatusHandler
.ensureFilesWritable(project
, file
)) {
97 ApplicationManager
.getApplication().invokeLater(new Runnable() {
99 if (editor
!= null && editor
.getComponent().isDisplayable()) {
100 HintManager
.getInstance()
101 .showErrorHint(editor
, CodeInsightBundle
.message("error.hint.file.is.readonly", file
.getPresentableUrl()));
112 public static boolean preparePsiElementForWrite(PsiElement element
) {
113 PsiFile file
= element
== null ?
null : element
.getContainingFile();
114 return prepareFileForWrite(file
);
117 public static boolean preparePsiElementsForWrite(PsiElement
... elements
) {
118 return preparePsiElementsForWrite(Arrays
.asList(elements
));
120 public static boolean preparePsiElementsForWrite(Collection
<?
extends PsiElement
> elements
) {
121 if (elements
.isEmpty()) return true;
122 Set
<VirtualFile
> files
= new THashSet
<VirtualFile
>();
123 Project project
= null;
124 for (PsiElement element
: elements
) {
125 project
= element
.getProject();
126 PsiFile file
= element
.getContainingFile();
127 if (file
== null) continue;
128 VirtualFile virtualFile
= file
.getVirtualFile();
129 if (virtualFile
== null) continue;
130 files
.add(virtualFile
);
132 if (!files
.isEmpty()) {
133 VirtualFile
[] virtualFiles
= VfsUtil
.toVirtualFileArray(files
);
134 ReadonlyStatusHandler
.OperationStatus status
= ReadonlyStatusHandler
.getInstance(project
).ensureFilesWritable(virtualFiles
);
135 return !status
.hasReadonlyFiles();