From 9abb7eedaae661a7a79aa30a807a4ef33f0cd8e4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 7 Nov 2014 18:13:02 +0100 Subject: [PATCH 1/4] PCE from running invalidation tasks should reschedule file processing --- .../src/com/intellij/util/indexing/FileBasedIndexImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index d8e566c71034..48cf63103139 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -2287,7 +2287,12 @@ public class FileBasedIndexImpl extends FileBasedIndex { removeFileDataFromIndices(ContainerUtil.intersection(nontrivialFileIndexedStates, myRequiringContentIndices), file); } else { - doIndexFileContent(project, fileContent); + try { + doIndexFileContent(project, fileContent); + } catch (ProcessCanceledException ex) { + myFilesToUpdate.add(file); // PCE from running invalidation tasks should reschedule file processing + throw ex; + } } } finally { From 9b3f15c35d1b38441589f6bb02a34310b18b1f09 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 7 Nov 2014 19:41:54 +0100 Subject: [PATCH 2/4] cache light tree in file content only --- .../intellij/psi/stubs/LightStubBuilder.java | 30 ++++++++++++------- .../psi/impl/source/tree/FileElement.java | 17 +---------- .../source/tree/LazyParseableElement.java | 6 +--- .../intellij/psi/stubs/StubTreeBuilder.java | 10 +++++-- .../util/indexing/FileContentImpl.java | 11 +++++++ .../util/indexing/IndexingDataKeys.java | 2 ++ .../dupLocator/LightDuplicateProfile.java | 6 ++-- .../dupLocator/index/DuplicatesIndex.java | 11 +++---- .../index/DuplicatesInspectionBase.java | 7 +++-- 9 files changed, 55 insertions(+), 45 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java index e9dec24fca2c..9ed329bc6dbf 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java +++ b/platform/core-api/src/com/intellij/psi/stubs/LightStubBuilder.java @@ -33,21 +33,25 @@ import java.util.List; public class LightStubBuilder implements StubBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.LightStubBuilder"); + private LighterAST myForcedLighterAst; @Override public StubElement buildStubTree(@NotNull PsiFile file) { - FileType fileType = file.getFileType(); - if (!(fileType instanceof LanguageFileType)) { - LOG.error("File is not of LanguageFileType: " + fileType + ", " + file); - return null; + LighterAST tree = myForcedLighterAst; + if (tree == null) { + FileType fileType = file.getFileType(); + if (!(fileType instanceof LanguageFileType)) { + LOG.error("File is not of LanguageFileType: " + fileType + ", " + file); + return null; + } + Language language = ((LanguageFileType)fileType).getLanguage(); + final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType(); + if (!(contentType instanceof ILightStubFileElementType)) { + LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file); + return null; + } + tree = file.getNode().getLighterAST(); } - Language language = ((LanguageFileType)fileType).getLanguage(); - final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType(); - if (!(contentType instanceof ILightStubFileElementType)) { - LOG.error("File is not of ILightStubFileElementType: " + contentType + ", " + file); - return null; - } - final LighterAST tree = file.getNode().getLighterAST(); if (tree == null) return null; final StubElement rootStub = createStubForFile(file, tree); @@ -154,4 +158,8 @@ public class LightStubBuilder implements StubBuilder { protected boolean skipChildProcessingWhenBuildingStubs(@NotNull LighterAST tree, @NotNull LighterASTNode parent, @NotNull LighterASTNode node) { return false; } + + public void setForcedLighterAst(LighterAST forcedLighterAst) { + myForcedLighterAst = forcedLighterAst; + } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java index 75b372cfc8ba..8192070f97c6 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java @@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.tree; import com.intellij.lang.*; import com.intellij.openapi.util.Getter; -import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.CharTableImpl; @@ -26,7 +25,6 @@ import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.ILightStubFileElementType; -import com.intellij.reference.SoftReference; import com.intellij.util.CharTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,8 +49,6 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge return myCharTable; } - private static final Key> ourTreeKey = Key.create("lighter.key"); - @Nullable @Override public LighterAST getLighterAST() { @@ -61,12 +57,7 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge LighterAST tree; if (!isParsed()) { - tree = SoftReference.dereference(getUserData(ourTreeKey)); - if (tree == null) { - final ILightStubFileElementType type = (ILightStubFileElementType)contentType; - tree = new FCTSBackedLighterAST(getCharTable(), type.parseContentsLight(this)); - tree = SoftReference.dereference(putUserDataIfAbsent(ourTreeKey, new SoftReference(tree))); - } + return new FCTSBackedLighterAST(getCharTable(), ((ILightStubFileElementType)contentType).parseContentsLight(this)); } else { tree = new TreeBackedLighterAST(this); @@ -74,12 +65,6 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge return tree; } - @Override - protected void resetCachesOnParsedStateUpdate() { - putUserData(ourTreeKey, null); - super.resetCachesOnParsedStateUpdate(); - } - public FileElement(IElementType type, CharSequence text) { super(type, text); } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index 85a28f195282..0dd85dfafcb6 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -182,7 +182,7 @@ public class LazyParseableElement extends CompositeElement { LOG.error("Reentrant parsing?"); } - resetCachesOnParsedStateUpdate(); + myText = null; if (parsedNode == null) return; super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode); @@ -199,10 +199,6 @@ public class LazyParseableElement extends CompositeElement { } } - protected void resetCachesOnParsedStateUpdate() { - myText = null; - } - @Override public void rawAddChildrenWithoutNotifications(@NotNull TreeElement first) { if (myText() != null) { diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java index 284704cf3962..af76f62331fd 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java @@ -21,6 +21,7 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiFile; +import com.intellij.psi.StubBuilder; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; import com.intellij.util.indexing.FileContent; @@ -56,7 +57,8 @@ public class StubTreeBuilder { final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); CharSequence contentAsText = inputData.getContentAsText(); - PsiFile psi = ((FileContentImpl)inputData).getPsiFileAccountingForUnsavedDocument(); + FileContentImpl fileContent = (FileContentImpl)inputData; + PsiFile psi = fileContent.getPsiFileAccountingForUnsavedDocument(); psi = psi.getViewProvider().getStubBindingRoot(); psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText); @@ -78,7 +80,11 @@ public class StubTreeBuilder { stubFileElementType = null; } if (stubFileElementType != null) { - data = stubFileElementType.getBuilder().buildStubTree(psi); + StubBuilder stubBuilder = stubFileElementType.getBuilder(); + if (stubBuilder instanceof LightStubBuilder) { // each builder is pristine + ((LightStubBuilder)stubBuilder).setForcedLighterAst(fileContent.getLighterAST()); + } + data = stubBuilder.buildStubTree(psi); } } finally { diff --git a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java index bd8309313e24..58521fdf0258 100644 --- a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java +++ b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java @@ -16,6 +16,7 @@ package com.intellij.util.indexing; import com.intellij.lang.Language; +import com.intellij.lang.LighterAST; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; @@ -78,6 +79,16 @@ public final class FileContentImpl extends UserDataHolderBase implements FileCon return psi; } + public @NotNull LighterAST getLighterAST() { + LighterAST lighterAST = getUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY); + if (lighterAST == null) { + lighterAST = getPsiFileAccountingForUnsavedDocument().getNode().getLighterAST(); + assert lighterAST != null; + putUserData(IndexingDataKeys.LIGHTER_AST_NODE_KEY, lighterAST); + } + return lighterAST; + } + public PsiFile createFileFromText(@NotNull CharSequence text) { Project project = getProject(); if (project == null) { diff --git a/platform/core-impl/src/com/intellij/util/indexing/IndexingDataKeys.java b/platform/core-impl/src/com/intellij/util/indexing/IndexingDataKeys.java index 9bd34a57b775..22fde5a4e2df 100644 --- a/platform/core-impl/src/com/intellij/util/indexing/IndexingDataKeys.java +++ b/platform/core-impl/src/com/intellij/util/indexing/IndexingDataKeys.java @@ -15,6 +15,7 @@ */ package com.intellij.util.indexing; +import com.intellij.lang.LighterAST; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; @@ -28,6 +29,7 @@ public class IndexingDataKeys { public static final Key PROJECT = new Key("Context project"); public static final Key PSI_FILE = new Key("PSI for stubs"); public static final Key FILE_TEXT_CONTENT_KEY = Key.create("file text content cached by stub indexer"); + public static final Key LIGHTER_AST_NODE_KEY = Key.create("lighter.ast.node"); private IndexingDataKeys() { } diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java index c3011c11454e..65f4815cb765 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/LightDuplicateProfile.java @@ -17,15 +17,15 @@ package com.intellij.dupLocator; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; -import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; /** * Created by Maxim.Mossienko on 10/1/2014. */ public interface LightDuplicateProfile { - void process(PsiFile file, Callback callback); + void process(@NotNull LighterAST ast, @NotNull Callback callback); interface Callback { - void process(LighterAST ast, LighterASTNode node, int hash); + void process(@NotNull LighterAST ast, @NotNull LighterASTNode node, int hash); } } diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java index cf4249cecd65..90b3dc93f387 100644 --- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java +++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java @@ -29,7 +29,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiFile; import com.intellij.util.SystemProperties; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; @@ -116,13 +115,15 @@ public class DuplicatesIndex extends FileBasedIndexExtension result = new THashMap(); - ((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() { + LighterAST ast = fileContent.getLighterAST(); + assert ast != null; + ((LightDuplicateProfile)profile).process(ast, new LightDuplicateProfile.Callback() { @Override - public void process(LighterAST ast, LighterASTNode node, int hash) { + public void process(@NotNull LighterAST ast, @NotNull LighterASTNode node, int hash) { TIntArrayList list = result.get(hash); if (list == null) { result.put(hash, list = new TIntArrayList(1)); } list.add(node.getStartOffset()); @@ -133,7 +134,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension myProcessorRef = new Ref(); if (profile instanceof LightDuplicateProfile && DuplicatesIndex.ourEnabledLightProfiles) { - - ((LightDuplicateProfile)profile).process(psiFile, new LightDuplicateProfile.Callback() { + LighterAST ast = psiFile.getNode().getLighterAST(); + assert ast != null; + ((LightDuplicateProfile)profile).process(ast, new LightDuplicateProfile.Callback() { DuplicatedCodeProcessor myProcessor; @Override - public void process(final LighterAST ast, final LighterASTNode node, int hash) { + public void process(@NotNull final LighterAST ast, @NotNull final LighterASTNode node, int hash) { class LightDuplicatedCodeProcessor extends DuplicatedCodeProcessor { LightDuplicatedCodeProcessor(VirtualFile file, Project project) { From 483086e897a1967823a7bef51fb1c0e23fbeb9cb Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 7 Nov 2014 22:20:12 +0300 Subject: [PATCH 3/4] cleanup: make border & border color configurable --- .../editor/impl/EditorHeaderComponent.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java index 31b3a56d2317..0833319cc010 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java @@ -17,6 +17,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; +import com.intellij.ui.border.CustomLineBorder; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -30,6 +31,7 @@ public class EditorHeaderComponent extends JPanel { public EditorHeaderComponent() { super(new BorderLayout(0, 0)); + setBorder(new CustomLineBorder(JBColor.border(), 0, UIUtil.isUnderGTKLookAndFeel()? 0 : 1, 1, 0)); } @Override @@ -43,6 +45,8 @@ public class EditorHeaderComponent extends JPanel { @Override protected void paintComponent(@NotNull Graphics g) { super.paintComponent(g); + if (UIUtil.isUnderGTKLookAndFeel()) return; + paintGradient(g, this); } @@ -53,13 +57,8 @@ public class EditorHeaderComponent extends JPanel { Graphics2D g2d = (Graphics2D)g; - if (!UIUtil.isUnderGTKLookAndFeel()) { - g2d.setPaint(UIUtil.getGradientPaint(0, 0, GRADIENT_C1, 0, c.getHeight(), GRADIENT_C2)); - g2d.fillRect(1, 1, c.getWidth(), c.getHeight() - 1); - g2d.setPaint(null); - } - - g.setColor(UIUtil.getBorderColor()); - g.drawLine(0, c.getHeight() - 1, c.getWidth(), c.getHeight() - 1); + g2d.setPaint(UIUtil.getGradientPaint(0, 0, GRADIENT_C1, 0, c.getHeight(), GRADIENT_C2)); + g2d.fillRect(0, 0, c.getWidth(), c.getHeight() - 1); + g2d.setPaint(null); } } From 13739618cd58335cc87c30e9a1b647a802687723 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 7 Nov 2014 21:45:50 +0100 Subject: [PATCH 4/4] ui: insets around facet validator component --- .../facet/impl/ui/FacetEditorImpl.java | 18 +++++++++++++----- .../facet/impl/ui/FacetErrorPanel.java | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java index 4c469053ca9d..41868ba87529 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/FacetEditorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.facet.impl.ui; import com.intellij.facet.Facet; @@ -61,6 +60,7 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed } } + @Override public void reset() { super.reset(); myErrorPanel.getValidatorsManager().validate(); @@ -73,6 +73,7 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed return myComponent; } + @Override public JComponent createComponent() { final JComponent editorComponent; if (myEditorTabs.length > 1) { @@ -83,7 +84,8 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed tabbedPane.addTab(editorTab.getDisplayName(), c); } tabbedPane.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { + @Override + public void stateChanged(@NotNull ChangeEvent e) { myEditorTabs[mySelectedTabIndex].onTabLeaving(); mySelectedTabIndex = tabbedPane.getSelectedIndex(); onTabSelected(myEditorTabs[mySelectedTabIndex]); @@ -99,10 +101,13 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed else { editorComponent = new JPanel(); } + + final JComponent errorComponent = myErrorPanel.getComponent(); + UIUtil.addInsets(errorComponent, new Insets(0, 5, 5, 0)); + final JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, editorComponent); - panel.add(BorderLayout.SOUTH, myErrorPanel.getComponent()); - + panel.add(BorderLayout.SOUTH, errorComponent); return panel; } @@ -122,6 +127,7 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed } } + @Override public void disposeUIResources() { Disposer.dispose(myDisposable); myErrorPanel.disposeUIResources(); @@ -161,10 +167,12 @@ public class FacetEditorImpl extends UnnamedConfigurableGroup implements Unnamed } } + @Override public FacetEditorTab[] getEditorTabs() { return myEditorTabs; } + @Override public T getEditorTab(@NotNull final Class aClass) { for (FacetEditorTab editorTab : myEditorTabs) { if (aClass.isInstance(editorTab)) { diff --git a/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java b/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java index 2de03c48df91..d5402689f415 100644 --- a/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java +++ b/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.facet.impl.ui; import com.intellij.facet.ui.FacetConfigurationQuickFix; @@ -52,9 +51,10 @@ public class FacetErrorPanel { myValidatorsManager = new FacetValidatorsManagerImpl(); myWarningLabel = new JLabel(); myWarningLabel.setIcon(AllIcons.General.WarningDialog); + myWarningLabel.setIconTextGap(5); myQuickFixButton.addActionListener(new ActionListener() { @Override - public void actionPerformed(final ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { if (myCurrentQuickFix != null) { myCurrentQuickFix.run(myQuickFixButton); myValidatorsManager.validate();