mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-67711
This commit is contained in:
@@ -52,12 +52,12 @@ class AnchorElementInfo extends SelfElementInfo {
|
||||
@Nullable
|
||||
public PsiElement restoreElement() {
|
||||
if (stubId != -1) {
|
||||
PsiFile file = SelfElementInfo.restoreFileFromVirtual(myVirtualFile, myProject);
|
||||
PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
|
||||
if (!(file instanceof PsiFileWithStubSupport)) return null;
|
||||
return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType);
|
||||
}
|
||||
if (!mySyncMarkerIsValid) return null;
|
||||
PsiFile file = SelfElementInfo.restoreFileFromVirtual(myVirtualFile, myProject);
|
||||
PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject);
|
||||
if (file == null) return null;
|
||||
PsiElement anchor = file.findElementAt(getSyncStartOffset());
|
||||
if (anchor == null) return null;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* pointer to a PsiFile + range inside the file.
|
||||
@@ -25,5 +26,6 @@ public interface SmartPsiFileRange extends SmartPsiElementPointer<PsiFile> {
|
||||
/**
|
||||
* @return the range inside the PsiFile, or null if the range or PsiFile became invalid
|
||||
*/
|
||||
@Nullable
|
||||
Segment getRange();
|
||||
}
|
||||
|
||||
+1
-1
@@ -362,7 +362,7 @@ public class ReplaceInProjectManager {
|
||||
for (final Usage usage : selectedUsages) {
|
||||
final VirtualFile file = ((UsageInFile)usage).getFile();
|
||||
|
||||
if (!file.isWritable()) {
|
||||
if (file != null && !file.isWritable()) {
|
||||
if (readOnlyFiles == null) readOnlyFiles = new HashSet<VirtualFile>();
|
||||
readOnlyFiles.add(file);
|
||||
}
|
||||
|
||||
+47
-7
@@ -17,24 +17,64 @@ package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: cdr
|
||||
*/
|
||||
class InjectedSelfElementInfo extends SelfElementInfo {
|
||||
private final SmartPsiFileRange myPsiFileRangeInHostElement;
|
||||
private final Class<? extends PsiElement> myClass;
|
||||
|
||||
InjectedSelfElementInfo(@NotNull Project project,
|
||||
@NotNull PsiElement anchor,
|
||||
@NotNull PsiFile containingFile) {
|
||||
super(project, InjectedLanguageManager.getInstance(project).injectedToHost(anchor, anchor.getTextRange()), anchor.getClass(), InjectedLanguageUtil.getTopLevelFile(containingFile));
|
||||
assert containingFile.getContext() != null;
|
||||
@NotNull PsiElement context) {
|
||||
super(project, context);
|
||||
SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project);
|
||||
myPsiFileRangeInHostElement = smartPointerManager.createSmartPsiFileRangePointer(context.getContainingFile(), InjectedLanguageManager.getInstance(
|
||||
project).injectedToHost(anchor, anchor.getTextRange()));
|
||||
myClass = anchor.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement findAnchorAt(@NotNull PsiFile file, int syncStartOffset) {
|
||||
return InjectedLanguageUtil.findInjectedElementNoCommitWithOffset(file, syncStartOffset);
|
||||
public VirtualFile getVirtualFile() {
|
||||
PsiElement element = restoreElement();
|
||||
if (element == null) return null;
|
||||
return element.getContainingFile().getVirtualFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement restoreElement() {
|
||||
PsiElement host = super.restoreElement();
|
||||
if (host == null) return null;
|
||||
|
||||
Segment segment = myPsiFileRangeInHostElement.getRange();
|
||||
if (segment == null) return null;
|
||||
final TextRange rangeInHostElement = TextRange.create(segment);
|
||||
final Ref<PsiElement> result = new Ref<PsiElement>();
|
||||
|
||||
InjectedLanguageUtil.enumerate(host, host.getContainingFile(), new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (result.get() != null) return;
|
||||
TextRange hostRange =
|
||||
InjectedLanguageManager.getInstance(getProject()).injectedToHost(injectedPsi, new TextRange(0, injectedPsi.getTextLength()));
|
||||
if (hostRange.contains(rangeInHostElement)) {
|
||||
TextRange rangeInside = rangeInHostElement.shiftRight(-hostRange.getStartOffset());
|
||||
PsiElement element = findElementInside(injectedPsi, rangeInside.getStartOffset(), rangeInside.getEndOffset(), myClass);
|
||||
result.set(element);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.lang.ref.SoftReference;
|
||||
* User: cdr
|
||||
*/
|
||||
public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
protected final VirtualFile myVirtualFile;
|
||||
private final VirtualFile myVirtualFile;
|
||||
private Reference<RangeMarker> myMarkerRef; // create marker only in case of live document
|
||||
private int mySyncStartOffset;
|
||||
private int mySyncEndOffset;
|
||||
@@ -44,6 +44,9 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private RangeMarker myRangeMarker; //maintain hard reference during modification
|
||||
|
||||
protected SelfElementInfo(@NotNull Project project, @NotNull PsiElement anchor) {
|
||||
this(project, anchor.getTextRange(), anchor.getClass(), anchor.getContainingFile());
|
||||
}
|
||||
public SelfElementInfo(@NotNull Project project, @NotNull TextRange anchor, @NotNull Class anchorClass, @NotNull PsiFile containingFile) {
|
||||
myVirtualFile = containingFile.getVirtualFile();
|
||||
myType = anchorClass;
|
||||
@@ -154,7 +157,11 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
final int syncStartOffset = getSyncStartOffset();
|
||||
final int syncEndOffset = getSyncEndOffset();
|
||||
|
||||
PsiElement anchor = findAnchorAt(file, syncStartOffset);
|
||||
return findElementInside(file, syncStartOffset, syncEndOffset, myType);
|
||||
}
|
||||
|
||||
protected static PsiElement findElementInside(PsiFile file, int syncStartOffset, int syncEndOffset, Class type) {
|
||||
PsiElement anchor = file.getViewProvider().findElementAt(syncStartOffset, file.getLanguage());
|
||||
if (anchor == null) return null;
|
||||
|
||||
TextRange range = anchor.getTextRange();
|
||||
@@ -166,7 +173,7 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
range = anchor.getTextRange();
|
||||
}
|
||||
|
||||
while (range.getEndOffset() == syncEndOffset && anchor != null && !myType.equals(anchor.getClass())) {
|
||||
while (range.getEndOffset() == syncEndOffset && anchor != null && !type.equals(anchor.getClass())) {
|
||||
anchor = anchor.getParent();
|
||||
if (anchor == null || anchor.getTextRange() == null) break;
|
||||
range = anchor.getTextRange();
|
||||
@@ -176,10 +183,6 @@ public class SelfElementInfo implements SmartPointerElementInfo {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected PsiElement findAnchorAt(@NotNull PsiFile file, int syncStartOffset) {
|
||||
return file.getViewProvider().findElementAt(syncStartOffset, file.getLanguage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
RangeMarker marker = getMarker();
|
||||
|
||||
+2
-1
@@ -153,7 +153,8 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
|
||||
|
||||
FileViewProvider viewProvider = containingFile.getViewProvider();
|
||||
if (viewProvider instanceof InjectedFileViewProvider) {
|
||||
return new InjectedSelfElementInfo(project, element, containingFile);
|
||||
PsiElement context = containingFile.getContext();
|
||||
if (context != null) return new InjectedSelfElementInfo(project, element, context);
|
||||
}
|
||||
|
||||
if (element instanceof PsiFile) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.usages;
|
||||
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -101,10 +103,11 @@ public class ChunkExtractor {
|
||||
private ChunkExtractor(@NotNull PsiFile file) {
|
||||
myColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
|
||||
|
||||
myDocument = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
|
||||
Project project = file.getProject();
|
||||
myDocument = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
LOG.assertTrue(myDocument != null);
|
||||
final FileType fileType = file.getFileType();
|
||||
final SyntaxHighlighter highlighter = SyntaxHighlighter.PROVIDER.create(fileType, file.getProject(), file.getVirtualFile());
|
||||
final SyntaxHighlighter highlighter = SyntaxHighlighter.PROVIDER.create(fileType, project, file.getVirtualFile());
|
||||
myHighlighter = highlighter == null ? new PlainSyntaxHighlighter() : highlighter;
|
||||
myLexer = myHighlighter.getHighlightingLexer();
|
||||
myLexer.start(myDocument.getCharsSequence());
|
||||
@@ -125,8 +128,15 @@ public class ChunkExtractor {
|
||||
int absoluteStartOffset = usageInfo2UsageAdapter.getNavigationOffset();
|
||||
if (absoluteStartOffset == -1) return TextChunk.EMPTY_ARRAY;
|
||||
|
||||
final int lineNumber = myDocument.getLineNumber(absoluteStartOffset);
|
||||
final int columnNumber = absoluteStartOffset - myDocument.getLineStartOffset(lineNumber);
|
||||
Document visibleDocument = myDocument instanceof DocumentWindow ? ((DocumentWindow)myDocument).getDelegate() : myDocument;
|
||||
int visibleStartOffset = myDocument instanceof DocumentWindow ? ((DocumentWindow)myDocument).injectedToHost(absoluteStartOffset) : absoluteStartOffset;
|
||||
|
||||
int lineNumber = myDocument.getLineNumber(absoluteStartOffset);
|
||||
//int columnNumber = absoluteStartOffset - myDocument.getLineStartOffset(lineNumber);
|
||||
int visibleLineNumber = visibleDocument.getLineNumber(visibleStartOffset);
|
||||
int visibleColumnNumber = visibleStartOffset - visibleDocument.getLineStartOffset(visibleLineNumber);
|
||||
final List<TextChunk> result = new ArrayList<TextChunk>();
|
||||
appendPrefix(result, visibleLineNumber, visibleColumnNumber);
|
||||
|
||||
int lineStartOffset = myDocument.getLineStartOffset(lineNumber);
|
||||
int lineEndOffset = lineStartOffset < myDocument.getTextLength() ? myDocument.getLineEndOffset(lineNumber) : 0;
|
||||
@@ -136,8 +146,6 @@ public class ChunkExtractor {
|
||||
if (myLexer.getTokenStart() > absoluteStartOffset) {
|
||||
myLexer.start(chars);
|
||||
}
|
||||
final List<TextChunk> result = new ArrayList<TextChunk>();
|
||||
appendPrefix(result, lineNumber, columnNumber);
|
||||
if (lineEndOffset - lineStartOffset > MAX_LINE_TO_SHOW) {
|
||||
lineStartOffset = Math.max(lineStartOffset, absoluteStartOffset - OFFSET_BEFORE_TO_SHOW_WHEN_LONG_LINE);
|
||||
lineEndOffset = Math.min(lineEndOffset, absoluteStartOffset + OFFSET_AFTER_TO_SHOW_WHEN_LONG_LINE);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class UsageDataUtil {
|
||||
for (Usage usage : usages) {
|
||||
if (usage instanceof UsageInFile) {
|
||||
VirtualFile file = ((UsageInFile)usage).getFile();
|
||||
if (file.isValid()) {
|
||||
if (file != null && file.isValid()) {
|
||||
result.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.usages;
|
||||
|
||||
import com.intellij.ide.SelectInEditorManager;
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.actionSystem.DataSink;
|
||||
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
|
||||
@@ -79,7 +80,7 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
|
||||
@Override
|
||||
public void run() {
|
||||
PsiElement element = getElement();
|
||||
Document document = getDocument();
|
||||
Document document = PsiDocumentManager.getInstance(getProject()).getDocument(element.getContainingFile());
|
||||
int startOffset = myUsageInfo.getNavigationOffset();
|
||||
|
||||
if (document != null) {
|
||||
@@ -197,7 +198,8 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
|
||||
}
|
||||
|
||||
public boolean canNavigate() {
|
||||
return getFile().isValid();
|
||||
VirtualFile file = getFile();
|
||||
return file != null && file.isValid();
|
||||
}
|
||||
|
||||
public boolean canNavigateToSource() {
|
||||
@@ -323,16 +325,27 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
|
||||
return myUsageInfo;
|
||||
}
|
||||
|
||||
// by start offset
|
||||
public int compareTo(final UsageInfo2UsageAdapter o) {
|
||||
VirtualFile containingFile = getFile();
|
||||
int shift1 = 0;
|
||||
if (containingFile instanceof VirtualFileWindow) {
|
||||
shift1 = ((VirtualFileWindow)containingFile).getDocumentWindow().injectedToHost(0);
|
||||
containingFile = ((VirtualFileWindow)containingFile).getDelegate();
|
||||
}
|
||||
VirtualFile oContainingFile = o.getFile();
|
||||
int shift2 = 0;
|
||||
if (oContainingFile instanceof VirtualFileWindow) {
|
||||
shift2 = ((VirtualFileWindow)oContainingFile).getDocumentWindow().injectedToHost(0);
|
||||
oContainingFile = ((VirtualFileWindow)oContainingFile).getDelegate();
|
||||
}
|
||||
if (containingFile == null && oContainingFile == null || !Comparing.equal(containingFile, oContainingFile)) {
|
||||
return 0;
|
||||
}
|
||||
Segment s1 = getFirstSegment();
|
||||
Segment s2 = o.getFirstSegment();
|
||||
if (s1 == null || s2 == null) return 0;
|
||||
return s1.getStartOffset() - s2.getStartOffset();
|
||||
return s1.getStartOffset() + shift1 - s2.getStartOffset() - shift2;
|
||||
}
|
||||
|
||||
public void rename(String newName) throws IncorrectOperationException {
|
||||
|
||||
@@ -909,7 +909,8 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
|
||||
for (Usage usage : usages) {
|
||||
if (usage instanceof UsageInFile) {
|
||||
UsageInFile usageInFile = (UsageInFile)usage;
|
||||
result.add(usageInFile.getFile());
|
||||
VirtualFile file = usageInFile.getFile();
|
||||
if (file != null) result.add(file);
|
||||
}
|
||||
|
||||
if (usage instanceof UsageInFiles) {
|
||||
|
||||
Reference in New Issue
Block a user