IDEA-95627 Postgres stored functions cannot be formatted

1. Use only cached injected data;
2. Minor code style fixes;
This commit is contained in:
Denis.Zhdanov
2013-01-12 22:57:28 +04:00
parent e25773267b
commit a85c05cbed
6 changed files with 65 additions and 81 deletions
@@ -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;
}
@@ -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;
}
@@ -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
@@ -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();