mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-95627 Postgres stored functions cannot be formatted
1. Use only cached injected data; 2. Minor code style fixes;
This commit is contained in:
+13
-1
@@ -32,6 +32,7 @@ import com.intellij.testFramework.HighlightTestInfo;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -139,7 +140,14 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa
|
||||
protected List<HighlightInfo> doHighlighting() {
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
|
||||
int[] toIgnore = doFolding() ? ArrayUtil.EMPTY_INT_ARRAY : new int[]{Pass.UPDATE_FOLDING};
|
||||
TIntArrayList toIgnoreList = new TIntArrayList();
|
||||
if (!doFolding()) {
|
||||
toIgnoreList.add(Pass.UPDATE_FOLDING);
|
||||
}
|
||||
if (!doInspections()) {
|
||||
toIgnoreList.add(Pass.LOCAL_INSPECTIONS);
|
||||
}
|
||||
int[] toIgnore = toIgnoreList.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : toIgnoreList.toNativeArray();
|
||||
Editor editor = getEditor();
|
||||
PsiFile file = getFile();
|
||||
if (editor instanceof EditorWindow) {
|
||||
@@ -157,4 +165,8 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa
|
||||
protected boolean doFolding() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean doInspections() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
package com.intellij.psi.formatter.common;
|
||||
|
||||
import com.intellij.formatting.*;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.formatter.FormatterUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -79,26 +79,25 @@ public abstract class AbstractBlock implements ASTBlock {
|
||||
if (file == null) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
if (InjectedLanguageUtil.areInjectionsProcessed(file) && InjectedLanguageUtil.getCachedInjectedDocuments(file).isEmpty()) {
|
||||
|
||||
if (InjectedLanguageUtil.getCachedInjectedDocuments(file).isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
final Ref<PsiFile> injectedRef = new Ref<PsiFile>();
|
||||
InjectedLanguageUtil.enumerate(psi, file, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (injectedRef.get() == null) {
|
||||
injectedRef.set(injectedPsi);
|
||||
TextRange blockRange = myNode.getTextRange();
|
||||
List<DocumentWindow> documentWindows = InjectedLanguageUtil.getCachedInjectedDocuments(file);
|
||||
for (DocumentWindow documentWindow : documentWindows) {
|
||||
int startOffset = documentWindow.injectedToHost(0);
|
||||
int endOffset = startOffset + documentWindow.getTextLength();
|
||||
if (blockRange.containsRange(startOffset, endOffset)) {
|
||||
PsiFile injected = PsiDocumentManager.getInstance(psi.getProject()).getCachedPsiFile(documentWindow);
|
||||
if (injected != null) {
|
||||
List<Block> result = ContainerUtilRt.newArrayList();
|
||||
DefaultInjectedLanguageBlockBuilder builder = new DefaultInjectedLanguageBlockBuilder(((SettingsAwareBlock)this).getSettings());
|
||||
builder.addInjectedBlocks(result, myNode, getWrap(), getAlignment(), getIndent());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
});
|
||||
PsiFile injected = injectedRef.get();
|
||||
if (injected != null && myNode.getTextLength() >= injected.getTextLength()) {
|
||||
List<Block> result = new ArrayList<Block>();
|
||||
DefaultInjectedLanguageBlockBuilder builder = new DefaultInjectedLanguageBlockBuilder(((SettingsAwareBlock)this).getSettings());
|
||||
builder.addInjectedBlocks(result, myNode, getWrap(), getAlignment(), getIndent());
|
||||
return result;
|
||||
}
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
+30
-55
@@ -34,14 +34,12 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.formatter.DocumentBasedFormattingModel;
|
||||
@@ -58,8 +56,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class CodeFormatterFacade {
|
||||
@@ -236,59 +232,37 @@ public class CodeFormatterFacade {
|
||||
|
||||
PsiFile file = psi.getContainingFile();
|
||||
|
||||
// We use a set here because we encountered a situation when more than one PSI leaf points to the same injected fragment
|
||||
// (at least for sql injected into sql).
|
||||
final LinkedHashSet<TextRange> injectedFileRangesSet = ContainerUtilRt.newLinkedHashSet();
|
||||
if (InjectedLanguageUtil.areInjectionsProcessed(file)) {
|
||||
for (DocumentWindow window : InjectedLanguageUtil.getCachedInjectedDocuments(file)) {
|
||||
injectedFileRangesSet.add(TextRange.create(window.injectedToHost(0), window.injectedToHost(window.getTextLength())));
|
||||
}
|
||||
}
|
||||
else if (!file.getProject().isDefault()) {
|
||||
PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
Segment rangeMarker = place.getHostRangeMarker();
|
||||
injectedFileRangesSet.add(TextRange.create(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()));
|
||||
}
|
||||
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(file.getProject());
|
||||
List<DocumentWindow> injectedDocuments = InjectedLanguageUtil.getCachedInjectedDocuments(file);
|
||||
if (!injectedDocuments.isEmpty()) {
|
||||
List<DocumentWindow> injectedDocumentsToUse = ContainerUtilRt.newArrayList(injectedDocuments);
|
||||
for (DocumentWindow window : injectedDocumentsToUse) {
|
||||
if (!window.isValid()) {
|
||||
// There is a possible case that format pre-processor modifies target document in a way that some injections are dropped.
|
||||
continue;
|
||||
}
|
||||
};
|
||||
PsiFile injected = psiDocumentManager.getCachedPsiFile(window);
|
||||
if (injected != null) {
|
||||
int startHostOffset = window.injectedToHost(0);
|
||||
int endHostOffset = window.injectedToHost(window.getTextLength());
|
||||
int startInjectedOffset = range.getStartOffset() > startHostOffset ? startHostOffset - range.getStartOffset() : 0;
|
||||
int endInjectedOffset = injected.getTextLength();
|
||||
if (range.getEndOffset() < endHostOffset) {
|
||||
endInjectedOffset -= endHostOffset - range.getEndOffset();
|
||||
}
|
||||
final TextRange initialInjectedRange = TextRange.create(startInjectedOffset, endInjectedOffset);
|
||||
TextRange injectedRange = initialInjectedRange;
|
||||
for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
|
||||
injectedRange = processor.process(injected.getNode(), injectedRange);
|
||||
}
|
||||
|
||||
for (PsiElement e = PsiTreeUtil.getDeepestFirst(file); e != null; e = PsiTreeUtil.nextLeaf(e, true)) {
|
||||
InjectedLanguageUtil.enumerate(e, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
if (!injectedFileRangesSet.isEmpty()) {
|
||||
List<TextRange> ranges = ContainerUtilRt.newArrayList(injectedFileRangesSet);
|
||||
Collections.reverse(ranges);
|
||||
for (TextRange injectedFileRange : ranges) {
|
||||
int startHostOffset = injectedFileRange.getStartOffset();
|
||||
int endHostOffset = injectedFileRange.getEndOffset();
|
||||
if (startHostOffset >= range.getStartOffset() && endHostOffset <= range.getEndOffset()) {
|
||||
PsiFile injected = InjectedLanguageUtil.findInjectedPsiNoCommit(file, startHostOffset);
|
||||
if (injected != null) {
|
||||
int startInjectedOffset = range.getStartOffset() > startHostOffset ? startHostOffset - range.getStartOffset() : 0;
|
||||
int endInjectedOffset = injected.getTextLength();
|
||||
if (range.getEndOffset() < endHostOffset) {
|
||||
endInjectedOffset -= endHostOffset - range.getEndOffset();
|
||||
}
|
||||
final TextRange initialInjectedRange = TextRange.create(startInjectedOffset, endInjectedOffset);
|
||||
TextRange injectedRange = initialInjectedRange;
|
||||
for (PreFormatProcessor processor : Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
|
||||
injectedRange = processor.process(injected.getNode(), injectedRange);
|
||||
}
|
||||
|
||||
// Allow only range expansion (not reduction) for injected context.
|
||||
if ((initialInjectedRange.getStartOffset() > injectedRange.getStartOffset() && initialInjectedRange.getStartOffset() > 0)
|
||||
|| (initialInjectedRange.getEndOffset() < injectedRange.getEndOffset()
|
||||
&& initialInjectedRange.getEndOffset() < injected.getTextLength()))
|
||||
{
|
||||
range = TextRange.create(
|
||||
range.getStartOffset() + injectedRange.getStartOffset() - initialInjectedRange.getStartOffset(),
|
||||
range.getEndOffset() + initialInjectedRange.getEndOffset() - injectedRange.getEndOffset());
|
||||
}
|
||||
// Allow only range expansion (not reduction) for injected context.
|
||||
if ((initialInjectedRange.getStartOffset() > injectedRange.getStartOffset() && initialInjectedRange.getStartOffset() > 0)
|
||||
|| (initialInjectedRange.getEndOffset() < injectedRange.getEndOffset()
|
||||
&& initialInjectedRange.getEndOffset() < injected.getTextLength())) {
|
||||
range = TextRange.create(
|
||||
range.getStartOffset() + injectedRange.getStartOffset() - initialInjectedRange.getStartOffset(),
|
||||
range.getEndOffset() + initialInjectedRange.getEndOffset() - injectedRange.getEndOffset());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,6 +270,7 @@ public class CodeFormatterFacade {
|
||||
for(PreFormatProcessor processor: Extensions.getExtensions(PreFormatProcessor.EP_NAME)) {
|
||||
result = processor.process(node, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+1
-4
@@ -161,6 +161,7 @@ public class InjectedLanguageUtil {
|
||||
return EditorWindow.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiFile findInjectedPsiNoCommit(@NotNull PsiFile host, int offset) {
|
||||
PsiElement injected = findInjectedElementNoCommit(host, offset);
|
||||
return injected == null ? null : injected.getContainingFile();
|
||||
@@ -312,10 +313,6 @@ public class InjectedLanguageUtil {
|
||||
|
||||
private static final Key<List<DocumentWindow>> INJECTED_DOCS_KEY = Key.create("INJECTED_DOCS_KEY");
|
||||
|
||||
public static boolean areInjectionsProcessed(@NotNull PsiFile hostPsiFile) {
|
||||
return hostPsiFile.getUserData(INJECTED_DOCS_KEY) != null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<DocumentWindow> getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) {
|
||||
// modification of cachedInjectedDocuments must be under PsiLock only
|
||||
|
||||
+3
-2
@@ -27,6 +27,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.ParameterizedCachedValueProvider;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
@@ -53,8 +54,8 @@ class InjectedPsiCachedValueProvider implements ParameterizedCachedValueProvider
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static MultiHostRegistrarImpl doCompute(final PsiElement element,
|
||||
InjectedLanguageManagerImpl injectedManager,
|
||||
static MultiHostRegistrarImpl doCompute(@NotNull final PsiElement element,
|
||||
@NotNull InjectedLanguageManagerImpl injectedManager,
|
||||
Project project,
|
||||
PsiFile hostPsiFile) {
|
||||
MyInjProcessor processor = new MyInjProcessor(project, hostPsiFile);
|
||||
|
||||
@@ -51,7 +51,7 @@ class LeafPatcher extends RecursiveTreeElementWalkingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLeaf(LeafElement leaf) {
|
||||
public void visitLeaf(LeafElement leaf) {
|
||||
String leafText = leaf instanceof ForeignLeafPsiElement ? "" : leaf.getText();
|
||||
catLeafs.append(leafText);
|
||||
final TextRange leafRange = leaf.getTextRange();
|
||||
|
||||
Reference in New Issue
Block a user