From f5ea08c29aa551be0465636cb5ab7f7f71c3a5f0 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 10 Aug 2010 17:07:03 +0400 Subject: [PATCH 01/21] =?UTF-8?q?IDEA-24540:=20Parallel=20processing=20of?= =?UTF-8?q?=20model=20contributed=20(inspired=20by=20patch=20from=20Yann?= =?UTF-8?q?=20C=C3=A9bron)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ContributorsBasedGotoByModel.java | 95 +++++++++++-------- 1 file changed, 54 insertions(+), 41 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index 83f5480b033d..2e609988b096 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -15,23 +15,22 @@ */ package com.intellij.ide.util.gotoByName; +import com.intellij.concurrency.JobUtil; import com.intellij.ide.util.NavigationItemListCellRenderer; import com.intellij.navigation.ChooseByNameContributor; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.util.ArrayUtil; +import com.intellij.util.Processor; +import com.intellij.util.containers.ConcurrentHashSet; import com.intellij.util.containers.ContainerUtil; import javax.swing.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** * Contributor-based goto model @@ -51,24 +50,41 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel return new NavigationItemListCellRenderer(); } - public String[] getNames(boolean checkBoxState) { - Set names = new HashSet(); - for (ChooseByNameContributor contributor : myContributors) { - try { - ContainerUtil.addAll(names, contributor.getNames(myProject, checkBoxState)); + public String[] getNames(final boolean checkBoxState) { + final Set names = new ConcurrentHashSet(); + + JobUtil.invokeConcurrentlyUnderMyProgress(filterDumb(myContributors), new Processor() { + @Override + public boolean process(ChooseByNameContributor contributor) { + try { + ContainerUtil.addAll(names, contributor.getNames(myProject, checkBoxState)); + } + catch(ProcessCanceledException ex) { + // index corruption detected, ignore + } + catch(IndexNotReadyException ex) { + // index corruption detected, ignore + } + catch(Exception ex) { + LOG.error(ex); + } + return true; } - catch(ProcessCanceledException ex) { - // index corruption detected, ignore - } - catch(IndexNotReadyException ex) { - // index corruption detected, ignore - } - catch(Exception ex) { - LOG.error(ex); + }, false); + + return ArrayUtil.toStringArray(names); + } + + private List filterDumb(ChooseByNameContributor[] contributors) { + if (!DumbService.getInstance(myProject).isDumb()) return Arrays.asList(contributors); + List answer = new ArrayList(contributors.length); + for (ChooseByNameContributor contributor : contributors) { + if (DumbService.isDumbAware(contributor)) { + answer.add(contributor); } } - return ArrayUtil.toStringArray(names); + return answer; } /** @@ -81,33 +97,30 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel * which {@link #acceptItem(NavigationItem) returns true. * */ - public Object[] getElementsByName(String name, boolean checkBoxState, final String pattern) { - List items = null; - final boolean dumb = DumbService.getInstance(myProject).isDumb(); + public Object[] getElementsByName(final String name, final boolean checkBoxState, final String pattern) { + final List items = Collections.synchronizedList(new ArrayList()); - for (ChooseByNameContributor contributor : myContributors) { - try { - if (dumb && !DumbService.isDumbAware(contributor)) { - continue; - } - - for (NavigationItem item : contributor.getItemsByName(name, pattern, myProject, checkBoxState)) { - if (acceptItem(item)) { - if (items == null) { - items = new ArrayList(2); + JobUtil.invokeConcurrentlyUnderMyProgress(filterDumb(myContributors), new Processor() { + @Override + public boolean process(ChooseByNameContributor contributor) { + try { + for (NavigationItem item : contributor.getItemsByName(name, pattern, myProject, checkBoxState)) { + if (acceptItem(item)) { + items.add(item); } - items.add(item); } } + catch (ProcessCanceledException ex) { + // index corruption detected, ignore + } + catch (Exception ex) { + LOG.error(ex); + } + return true; } - catch(ProcessCanceledException ex) { - // index corruption detected, ignore - } - catch(Exception ex) { - LOG.error(ex); - } - } - return items == null ? ArrayUtil.EMPTY_OBJECT_ARRAY : ArrayUtil.toObjectArray(items); + }, false); + + return ArrayUtil.toObjectArray(items); } public String getElementName(Object element) { From 12795d25091facd70949740c24bd4e101b6df2e9 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 10 Aug 2010 14:19:54 +0400 Subject: [PATCH 02/21] ui designer: enable move forms via dnd (IDEA-57355) --- .../ide/projectView/impl/AbstractProjectViewPane.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java index ee435d453f58..d26c8e29051e 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java @@ -47,6 +47,7 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.pom.Navigatable; import com.intellij.psi.*; +import com.intellij.refactoring.actions.MoveAction; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionCache; import com.intellij.util.containers.HashMap; @@ -564,7 +565,7 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl }; //FavoritesManager.getInstance(myProject).getCurrentTreeViewPanel().setDraggableObject(draggableObject.getClass(), draggableObject.getValue()); - if ((psiElements != null && psiElements.length > 0) || canDragElements(elements)) { + if ((psiElements != null && psiElements.length > 0) || canDragElements(elements, dataContext, dge.getDragAction())) { dge.startDrag(DragSource.DefaultMoveNoDrop, new MyTransferable(transferableWrapper), myDragSourceListener); } } @@ -574,12 +575,16 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl } } - private boolean canDragElements(Object[] elements) { + private boolean canDragElements(Object[] elements, DataContext dataContext, int dragAction) { for (Object element : elements) { if (element instanceof Module) { return true; } } + if (dragAction == DnDConstants.ACTION_MOVE) { + final MoveAction.MoveProvider provider = MoveAction.MoveProvider.DATA_KEY.getData(dataContext); + return provider != null && provider.isEnabledOnDataContext(dataContext); + } return false; } } From c7ea1c0ab4e6ea3bd3a84159a96c65abd4ee183c Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 10 Aug 2010 15:36:21 +0400 Subject: [PATCH 03/21] too many strings --- .../src/com/intellij/psi/util/CachedValuesManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/psi/util/CachedValuesManager.java b/platform/platform-api/src/com/intellij/psi/util/CachedValuesManager.java index 9d133d787585..e2c805e5cc5e 100644 --- a/platform/platform-api/src/com/intellij/psi/util/CachedValuesManager.java +++ b/platform/platform-api/src/com/intellij/psi/util/CachedValuesManager.java @@ -89,7 +89,7 @@ public abstract class CachedValuesManager { public T getCachedValue(@NotNull D dataHolder, @NotNull CachedValueProvider provider) { - return getCachedValue(dataHolder, new MemoizationKey>("$CachedValue$" + provider.getClass().getName()), provider, false); + return getCachedValue(dataHolder, new MemoizationKey>(provider.getClass().getName()), provider, false); } public static class MemoizationKey extends Key { From d2e81ddadf802a67e0c3da0863a173dc45dd3de6 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 10 Aug 2010 17:08:16 +0400 Subject: [PATCH 04/21] drop caches more often --- .../intellij/codeInspection/reference/RefClassImpl.java | 1 + .../com/intellij/codeInspection/reference/RefManager.java | 3 +++ .../intellij/codeInspection/reference/RefManagerImpl.java | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java index 801e7c06ee4c..f795a456d373 100644 --- a/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java @@ -173,6 +173,7 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass { final PsiClass applet = getRefJavaManager().getApplet(); setApplet(applet != null && psiClass.isInheritor(applet, true)); getRefManager().fireNodeInitialized(this); + getRefManager().getPsiManager().dropResolveCaches(); } private void initializeSuperReferences(PsiClass psiClass) { diff --git a/platform/lang-api/src/com/intellij/codeInspection/reference/RefManager.java b/platform/lang-api/src/com/intellij/codeInspection/reference/RefManager.java index 10f281babd5b..7afc25a6d197 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/reference/RefManager.java +++ b/platform/lang-api/src/com/intellij/codeInspection/reference/RefManager.java @@ -20,6 +20,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiManager; import org.jdom.Element; import org.jetbrains.annotations.Nullable; @@ -108,4 +109,6 @@ public abstract class RefManager { public abstract String getQualifiedName(RefEntity refEntity); public abstract void removeRefElement(RefElement refElement, List deletedRefs); + + public abstract PsiManager getPsiManager(); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index 45a504890961..7cd9d653d98f 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -67,6 +67,7 @@ public class RefManagerImpl extends RefManager { private THashMap myModules; private final ProjectIterator myProjectIterator; private boolean myDeclarationsFound; + private final PsiManager myPsiManager; private boolean myIsInProcess = false; @@ -83,6 +84,7 @@ public class RefManagerImpl extends RefManager { myProject = project; myScope = scope; myContext = context; + myPsiManager = PsiManager.getInstance(project); myRefProject = new RefProjectImpl(this); myRefTable = new THashMap(); myProjectIterator = new ProjectIterator(); @@ -298,6 +300,11 @@ public class RefManagerImpl extends RefManager { return myRefTable; } + @Override + public PsiManager getPsiManager() { + return myPsiManager; + } + public void removeReference(RefElement refElem) { myLock.writeLock().lock(); try { @@ -366,6 +373,7 @@ public class RefManagerImpl extends RefManager { for (Language language : relevantLanguages) { visitElement(viewProvider.getPsi(language)); } + myPsiManager.dropResolveCaches(); } } From 0aaffd3c7b52f17ddbdf1c514b6eedfba1c864a3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 14:13:40 +0400 Subject: [PATCH 05/21] New Java parser (incomplete parameter list parsing fixed) --- .../lang/java/parser/DeclarationParser.java | 18 ++++--- .../declarationParsing/method/Errors3.java | 3 ++ .../declarationParsing/method/Errors3.txt | 51 +++++++++++++++++++ .../declarationParsing/MethodParsingTest.java | 1 + 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.java create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 4fe2ca0b28ba..e6478f816566 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -445,6 +445,7 @@ public class DeclarationParser { builder.advanceLexer(); PsiBuilder.Marker invalidElements = null; + String errorMessage = null; boolean commaExpected = false; int paramCount = 0; while (true) { @@ -454,15 +455,19 @@ public class DeclarationParser { if (noLastParam) { error(builder, JavaErrorMessages.message("expected.identifier.or.type")); } - if (builder.getTokenType() == JavaTokenType.RPARENTH) { + if (tokenType == JavaTokenType.RPARENTH) { if (invalidElements != null) { - invalidElements.error(commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter")); + invalidElements.error(errorMessage); } invalidElements = null; builder.advanceLexer(); } else { if (!noLastParam) { + if (invalidElements != null) { + invalidElements.error(errorMessage); + } + invalidElements = null; error(builder, JavaErrorMessages.message("expected.rparen")); } } @@ -473,7 +478,7 @@ public class DeclarationParser { if (builder.getTokenType() == JavaTokenType.COMMA) { commaExpected = false; if (invalidElements != null) { - invalidElements.error(JavaErrorMessages.message("expected.parameter")); + invalidElements.error(errorMessage); invalidElements = null; } builder.advanceLexer(); @@ -485,7 +490,7 @@ public class DeclarationParser { if (param != null) { commaExpected = true; if (invalidElements != null) { - invalidElements.errorBefore(JavaErrorMessages.message("expected.comma"), param); + invalidElements.errorBefore(errorMessage, param); invalidElements = null; } paramCount++; @@ -501,6 +506,7 @@ public class DeclarationParser { } else { invalidElements = builder.mark(); + errorMessage = commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter"); } } @@ -512,7 +518,7 @@ public class DeclarationParser { } if (invalidElements != null) { - invalidElements.error(commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter")); + invalidElements.error(errorMessage); } paramList.done(JavaElementType.PARAMETER_LIST); @@ -545,7 +551,7 @@ public class DeclarationParser { else { error(builder, JavaErrorMessages.message("expected.identifier")); param.drop(); - return type; + return modListInfo.first; } } diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.java b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.java new file mode 100644 index 000000000000..c8eadab3ea28 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.java @@ -0,0 +1,3 @@ +public class Test { + void foo( +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.txt new file mode 100644 index 000000000000..0a0e269675cd --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/method/Errors3.txt @@ -0,0 +1,51 @@ +PsiJavaFile:Errors3.java + PsiImportList + + PsiClass:Test + PsiModifierList:public + PsiKeyword:public('public') + PsiWhiteSpace(' ') + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:Test('Test') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiMethod:foo + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:foo('foo') + PsiParameterList:( + PsiJavaToken:LPARENTH('(') + PsiErrorElement:Parameter expected + PsiJavaToken:LT('<') + PsiModifierList: + + PsiTypeElement:caret + PsiJavaCodeReferenceElement:caret + PsiIdentifier:caret('caret') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiErrorElement:',' expected + PsiJavaToken:GT('>') + PsiErrorElement:')' expected + + PsiReferenceList + + PsiErrorElement:'{' or ';' expected + + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/MethodParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/MethodParsingTest.java index 6932fdcd2e56..e9a3b9559e58 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/MethodParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/MethodParsingTest.java @@ -23,6 +23,7 @@ public class MethodParsingTest extends JavaParsingTestCase { public void testErrors0() { doTest(true); } public void testErrors1() { doTest(true); } public void testErrors2() { doTest(true); } + public void testErrors3() { doTest(true); } public void testCompletionHack() { doTest(true); } public void testCompletionHack1() { doTest(true); } From 11adf2d476442120a2b1dbc520a3b4097df15853 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 14:24:15 +0400 Subject: [PATCH 06/21] New Java parser (incomplete class declaration parsing fixed) --- .../lang/java/parser/DeclarationParser.java | 3 +- .../class/{Error.java => Errors0.java} | 0 .../class/{Error.txt => Errors0.txt} | 2 +- .../declarationParsing/class/Errors1.java | 4 ++ .../declarationParsing/class/Errors1.txt | 42 +++++++++++++++++++ .../declarationParsing/ClassParsingTest.java | 3 +- 6 files changed, 51 insertions(+), 3 deletions(-) rename java/java-tests/testData/psi/parser-full/declarationParsing/class/{Error.java => Errors0.java} (100%) rename java/java-tests/testData/psi/parser-full/declarationParsing/class/{Error.txt => Errors0.txt} (96%) create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.java create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index e6478f816566..bc0e2f36089c 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -87,7 +87,8 @@ public class DeclarationParser { } error.error(JavaErrorMessages.message("expected.lbrace")); } - else { + + if (builder.getTokenType() == JavaTokenType.LBRACE) { parseClassBodyWithBraces(builder, isAnnotation, isEnum); } diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Error.java b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors0.java similarity index 100% rename from java/java-tests/testData/psi/parser-full/declarationParsing/class/Error.java rename to java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors0.java diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Error.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors0.txt similarity index 96% rename from java/java-tests/testData/psi/parser-full/declarationParsing/class/Error.txt rename to java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors0.txt index 4adc49249ad8..d94bbafd54bd 100644 --- a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Error.txt +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors0.txt @@ -1,4 +1,4 @@ -PsiJavaFile:Error.java +PsiJavaFile:Errors0.java PsiImportList PsiModifierList:public diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.java b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.java new file mode 100644 index 000000000000..4b1de6f4b802 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.java @@ -0,0 +1,4 @@ +// "Replace Implements with Static Import" "true" +interface In { + int FOO = 0; +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.txt new file mode 100644 index 000000000000..f98dc0da3bbf --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors1.txt @@ -0,0 +1,42 @@ +PsiJavaFile:Errors1.java + PsiImportList + + PsiClass:I + PsiComment(END_OF_LINE_COMMENT)('// "Replace Implements with Static Import" "true"') + PsiWhiteSpace('\n') + PsiModifierList: + + PsiKeyword:interface('interface') + PsiWhiteSpace(' ') + PsiIdentifier:I('I') + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:caret + PsiIdentifier:caret('caret') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:GT('>') + PsiReferenceList + + PsiReferenceList + + PsiErrorElement:'{' expected + PsiIdentifier:n('n') + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiField:FOO + PsiModifierList: + + PsiTypeElement:int + PsiKeyword:int('int') + PsiWhiteSpace(' ') + PsiIdentifier:FOO('FOO') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java index 9b5d635ad306..80780cc683e6 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java @@ -37,5 +37,6 @@ public class ClassParsingTest extends JavaParsingTestCase { public void testExtraOpeningBraceInMethod() { doTestDefaultParser(true); } // todo: fix public void testExtraClosingBraceInMethod() { doTest(true); } - public void testError() { doTest(true); } + public void testErrors0() { doTest(true); } + public void testErrors1() { doTest(true); } } From 193b44dca1a484a50d37b9a03633a81400488895 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 14:57:41 +0400 Subject: [PATCH 07/21] Empty import list placement and comment binding (test data fixed) --- .../quickFix/changeParameterClass/after2.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/after2.java index 4c9dc1a15f0f..55c22735f179 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/after2.java @@ -1,5 +1,5 @@ -// "Make 'a' extend 'b'" "true" -class a extends b { +// "Make 'a' extend 'b'" "true" +class a extends b { void f(b b, Runnable r) { f(this, null); } From 7bab89a29ff1f4252947d1b2eb9f454786f87aca Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 15:44:12 +0400 Subject: [PATCH 08/21] New Java parser (incomplete reference parsing fixed) --- .../lang/java/parser/ReferenceParser.java | 1 + .../commonParsing/RefParamsAfterError.java | 3 + .../commonParsing/RefParamsAfterError.txt | 100 ++++++++++++++++++ .../parser-partial/files/UnclosedPackage1.txt | 2 + .../parser-partial/references/Reference1.txt | 2 + .../java/parser/CommonJavaParsingTest.java | 3 +- 6 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.java create mode 100644 java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 3097261df7fc..97d62fb1453c 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -210,6 +210,7 @@ public class ReferenceParser { } else { error(builder, JavaErrorMessages.message("expected.identifier")); + emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST); break; } } diff --git a/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.java b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.java new file mode 100644 index 000000000000..931d101e074b --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.java @@ -0,0 +1,3 @@ +class C { + BCSSChild.BCSSCServiceClassRef fd = null; +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt new file mode 100644 index 000000000000..fd394aa1ad24 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt @@ -0,0 +1,100 @@ +PsiJavaFile:RefParamsAfterError.java + PsiImportList + + PsiClass:C + PsiModifierList: + + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:C('C') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiModifierList: + + PsiTypeElement:BCSSChild. + PsiJavaCodeReferenceElement:BCSSChild. + PsiJavaCodeReferenceElement:BCSSChild + PsiIdentifier:BCSSChild('BCSSChild') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiErrorElement:Identifier expected + + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiModifierList: + + PsiErrorElement:Unexpected token + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:error + PsiIdentifier:error('error') + PsiElement(EXTENDS_BOUND_LIST) + + PsiErrorElement:'>' expected. + + PsiWhiteSpace(' ') + PsiTypeElement:descr + PsiJavaCodeReferenceElement:descr + PsiIdentifier:descr('descr') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiErrorElement:Unexpected token + PsiJavaToken:EQ('=') + PsiJavaToken:STRING_LITERAL('""') + PsiJavaToken:GT('>') + PsiModifierList: + + PsiTypeElement:BCSSCServiceClassRef< + PsiJavaCodeReferenceElement:BCSSCServiceClassRef< + PsiIdentifier:BCSSCServiceClassRef('BCSSCServiceClassRef') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiErrorElement:Identifier expected + + PsiErrorElement:'>' or ',' expected. + + PsiErrorElement:Identifier expected + + PsiErrorElement:Unexpected token + PsiJavaToken:DIV('/') + PsiModifierList: + + PsiTypeElement:error + PsiJavaCodeReferenceElement:error + PsiIdentifier:error('error') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiErrorElement:Unexpected token + PsiJavaToken:GT('>') + PsiWhiteSpace(' ') + PsiModifierList: + + PsiTypeElement:fd + PsiJavaCodeReferenceElement:fd + PsiIdentifier:fd('fd') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected token + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage1.txt b/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage1.txt index 5f8fe8f51214..df363a686b85 100644 --- a/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage1.txt +++ b/java/java-tests/testData/psi/parser-partial/files/UnclosedPackage1.txt @@ -10,6 +10,8 @@ PsiJavaFile:UnclosedPackage1.java PsiJavaToken:DOT('.') PsiErrorElement:Identifier expected + PsiReferenceParameterList + PsiErrorElement:';' expected PsiImportList diff --git a/java/java-tests/testData/psi/parser-partial/references/Reference1.txt b/java/java-tests/testData/psi/parser-partial/references/Reference1.txt index 9e9dbbe0ec86..19be605d1f26 100644 --- a/java/java-tests/testData/psi/parser-partial/references/Reference1.txt +++ b/java/java-tests/testData/psi/parser-partial/references/Reference1.txt @@ -7,3 +7,5 @@ PsiJavaFile:Reference1.java PsiJavaToken:DOT('.') PsiErrorElement:Identifier expected + PsiReferenceParameterList + \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/CommonJavaParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/CommonJavaParsingTest.java index 5498d782cd98..e316ceffa277 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/CommonJavaParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/CommonJavaParsingTest.java @@ -21,8 +21,7 @@ public class CommonJavaParsingTest extends JavaParsingTestCase{ } public void testSCR5202() { doTest(true); } - public void testIncompleteCodeBlock() { doTest(true); } - public void testImportListBug() { doTest(true); } + public void testRefParamsAfterError() { doTest(true); } } \ No newline at end of file From 5bac84751f622b07e0342423b420a18ccdcdb352 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 16:04:49 +0400 Subject: [PATCH 09/21] New Java parser (incomplete annotation parsing fixed) --- .../lang/java/parser/DeclarationParser.java | 12 +-- .../annotationParsing/annotation/Errors.java | 2 + .../annotationParsing/annotation/Errors.txt | 73 +++++++++++++++++++ .../annotation/{Simple.java => Simple1.java} | 0 .../annotation/{Simple.txt => Simple1.txt} | 2 +- .../AnnotationParsingTest.java | 4 +- 6 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.java create mode 100644 java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.txt rename java/java-tests/testData/psi/parser-full/annotationParsing/annotation/{Simple.java => Simple1.java} (100%) rename java/java-tests/testData/psi/parser-full/annotationParsing/annotation/{Simple.txt => Simple1.txt} (97%) diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index bc0e2f36089c..6e1a05ce07ad 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -741,8 +741,8 @@ public class DeclarationParser { PsiBuilder.Marker pair = builder.mark(); if (mayBeSimple) { - final PsiBuilder.Marker value = parseAnnotationValue(builder); - if (value != null && builder.getTokenType() != JavaTokenType.EQ) { + parseAnnotationValue(builder); + if (builder.getTokenType() != JavaTokenType.EQ) { pair.done(JavaElementType.NAME_VALUE_PAIR); return false; } @@ -762,9 +762,9 @@ public class DeclarationParser { return hasName; } - @Nullable + @NotNull private static PsiBuilder.Marker parseAnnotationValue(final PsiBuilder builder) { - final PsiBuilder.Marker result; + PsiBuilder.Marker result; final IElementType tokenType = builder.getTokenType(); if (tokenType == JavaTokenType.AT) { @@ -778,8 +778,10 @@ public class DeclarationParser { } if (result == null) { - error(builder, JavaErrorMessages.message("expected.value")); + result = builder.mark(); + result.error(JavaErrorMessages.message("expected.value")); } + return result; } diff --git a/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.java b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.java new file mode 100644 index 000000000000..200c37e7fa32 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.java @@ -0,0 +1,2 @@ +@Ann(0) class D { +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.txt b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.txt new file mode 100644 index 000000000000..9f1efdb6d2e4 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Errors.txt @@ -0,0 +1,73 @@ +PsiJavaFile:Errors.java + PsiImportList + + PsiClass:D + PsiModifierList:@Ann(0) + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Ann + PsiIdentifier:Ann('Ann') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiErrorElement:Value expected + + PsiErrorElement:',' or ')' expected + + PsiJavaToken:LT('<') + PsiNameValuePair + PsiIdentifier:error('error') + PsiErrorElement:'=' expected + + PsiWhiteSpace(' ') + PsiReferenceExpression:descr + PsiReferenceParameterList + + PsiIdentifier:descr('descr') + PsiErrorElement:',' or ')' expected + + PsiJavaToken:EQ('=') + PsiNameValuePair + PsiErrorElement:Identifier expected + + PsiErrorElement:'=' expected + + PsiBinaryExpression:"Cannot find method 'value'">0< + PsiBinaryExpression:"Cannot find method 'value'">0 + PsiLiteralExpression:"Cannot find method 'value'" + PsiJavaToken:STRING_LITERAL('"Cannot find method 'value'"') + PsiJavaToken:GT('>') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:LT('<') + PsiErrorElement:Expression expected + + PsiErrorElement:',' or ')' expected + + PsiJavaToken:DIV('/') + PsiNameValuePair + PsiIdentifier:error('error') + PsiErrorElement:'=' expected + + PsiErrorElement:Value expected + + PsiErrorElement:',' or ')' expected + + PsiJavaToken:GT('>') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:D('D') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple.java b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple1.java similarity index 100% rename from java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple.java rename to java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple1.java diff --git a/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple.txt b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple1.txt similarity index 97% rename from java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple.txt rename to java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple1.txt index 3bf8f2a6e61e..7213017754c0 100644 --- a/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple.txt +++ b/java/java-tests/testData/psi/parser-full/annotationParsing/annotation/Simple1.txt @@ -1,4 +1,4 @@ -PsiJavaFile:Simple.java +PsiJavaFile:Simple1.java PsiImportList PsiClass:TimeTravel diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/annotationParsing/AnnotationParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/annotationParsing/AnnotationParsingTest.java index dcaf2e0cf4dd..640107cf62cf 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/annotationParsing/AnnotationParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/annotationParsing/AnnotationParsingTest.java @@ -14,7 +14,7 @@ public class AnnotationParsingTest extends JavaParsingTestCase { } public void testMarker() { doTest(true); } - public void testSimple() { doTest(true); } + public void testSimple1() { doTest(true); } public void testSimple2() { doTest(true); } public void testComplex() { doTest(true); } public void testMultiple() { doTest(true); } @@ -40,4 +40,6 @@ public class AnnotationParsingTest extends JavaParsingTestCase { } }); } + + public void testErrors() { doTest(true); } } From 9b3d3c88ab963b1143d379b98f239a03da893aae Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 16:27:23 +0400 Subject: [PATCH 10/21] New Java parser (static import reference parsing fixed) --- .../intellij/lang/java/parser/ReferenceParser.java | 4 +++- .../psi/parser-partial/files/UnclosedImport3.txt | 11 +++++++++++ .../lang/java/parser/partial/FileParserTest.java | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/psi/parser-partial/files/UnclosedImport3.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 97d62fb1453c..5208b8b8f6d4 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -172,7 +172,9 @@ public class ReferenceParser { parseReferenceParameterList(builder, true); } else { - emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST); + if (!isStaticImport || builder.getTokenType() == JavaTokenType.DOT) { + emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST); + } } boolean hasIdentifier; diff --git a/java/java-tests/testData/psi/parser-partial/files/UnclosedImport3.txt b/java/java-tests/testData/psi/parser-partial/files/UnclosedImport3.txt new file mode 100644 index 000000000000..fbe7d0e99952 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/files/UnclosedImport3.txt @@ -0,0 +1,11 @@ +PsiJavaFile:UnclosedImport3.java + PsiImportList + PsiImportStaticStatement + PsiKeyword:import('import') + PsiWhiteSpace(' ') + PsiKeyword:static('static') + PsiWhiteSpace(' ') + PsiImportStaticReferenceElement:a + PsiIdentifier:a('a') + PsiErrorElement:';' expected + \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java index 52c831ee661e..a952d2a591ea 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/FileParserTest.java @@ -39,6 +39,7 @@ public class FileParserTest extends JavaParsingTestCase { public void testUnclosedImport0() { doParserTest("import"); } public void testUnclosedImport1() { doParserTest("import java.awt.*"); } public void testUnclosedImport2() { doParserTest("import java.awt."); } + public void testUnclosedImport3() { doParserTest("import static a"); } public void testFileWithClass() { doParserTest("package a;\n" + "import b;\n" + From 7f8ba694f25efb528620c72086cbff8f8b2440ec Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 16:58:19 +0400 Subject: [PATCH 11/21] New Java parser (incomplete class declaration parsing fixed) --- .../lang/java/parser/DeclarationParser.java | 3 +- .../declarationParsing/class/Errors2.java | 3 ++ .../declarationParsing/class/Errors2.txt | 38 +++++++++++++++++++ .../declarationParsing/ClassParsingTest.java | 1 + 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.java create mode 100644 java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 6e1a05ce07ad..b5645b47f9ca 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -246,7 +246,8 @@ public class DeclarationParser { if (expect(builder, JavaTokenType.AT)) { if (builder.getTokenType() == JavaTokenType.INTERFACE_KEYWORD) { - return parseClassFromKeyword(builder, declaration, true, context); + final PsiBuilder.Marker result = parseClassFromKeyword(builder, declaration, true, context); + return result != null ? result : modList; } else { declaration.rollbackTo(); diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.java b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.java new file mode 100644 index 000000000000..f2c4c89574ff --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.java @@ -0,0 +1,3 @@ +public class Main { +@interface +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.txt new file mode 100644 index 000000000000..64ff57387dd0 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/Errors2.txt @@ -0,0 +1,38 @@ +PsiJavaFile:Errors2.java + PsiImportList + + PsiClass:Main + PsiModifierList:public + PsiKeyword:public('public') + PsiWhiteSpace(' ') + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:Main('Main') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n') + PsiModifierList: + + PsiJavaToken:AT('@') + PsiKeyword:interface('interface') + PsiErrorElement:Identifier expected + + PsiWhiteSpace(' ') + PsiModifierList: + + PsiErrorElement:Identifier or type expected + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:caret + PsiIdentifier:caret('caret') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:GT('>') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java index 80780cc683e6..900c9f2d2d8b 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/declarationParsing/ClassParsingTest.java @@ -39,4 +39,5 @@ public class ClassParsingTest extends JavaParsingTestCase { public void testErrors0() { doTest(true); } public void testErrors1() { doTest(true); } + public void testErrors2() { doTest(true); } } From d6ec09cf71b1db5893da212ec9a3d6c3733aedc1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 10 Aug 2010 17:27:43 +0400 Subject: [PATCH 12/21] New Java parser (incomplete parenthesized expression parsing fixed) --- .../com/intellij/lang/java/parser/ExpressionParser.java | 7 ++++++- .../testData/psi/parser-partial/expressions/Parenth2.txt | 5 +++++ .../lang/java/parser/partial/ExpressionParserTest.java | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/psi/parser-partial/expressions/Parenth2.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index c74f80356438..c07e78dc3be0 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -27,6 +27,7 @@ import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.java.parser.JavaParserUtil.*; @@ -502,7 +503,11 @@ public class ExpressionParser { error(builder, JavaErrorMessages.message("expected.expression")); } - JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen")); + if (!expect(builder, JavaTokenType.RPARENTH)) { + if (inner != null) { + error(builder, JavaErrorMessages.message("expected.rparen")); + } + } parenth.done(JavaElementType.PARENTH_EXPRESSION); return parenth; diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Parenth2.txt b/java/java-tests/testData/psi/parser-partial/expressions/Parenth2.txt new file mode 100644 index 000000000000..9a1a35b4dd54 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Parenth2.txt @@ -0,0 +1,5 @@ +PsiJavaFile:Parenth2.java + PsiParenthesizedExpression:( + PsiJavaToken:LPARENTH('(') + PsiErrorElement:Expression expected + \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java index fe8edea5dc46..70bedeb20fed 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java @@ -49,6 +49,7 @@ public class ExpressionParserTest extends JavaParsingTestCase { public void testParenth0() { doParserTest("(c)"); } public void testParenth1() { doParserTest("(this).f--"); } + public void testParenth2() { doParserTest("("); } public void testNewInExprList() { doParserTest("call(new)"); } From 0091e946189dd53688a2cf7d12e8ca64fef4861a Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 10 Aug 2010 18:53:45 +0400 Subject: [PATCH 13/21] file files by mask --- .../src/com/intellij/openapi/util/io/FileUtil.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index de18c57d41e0..cef4d68a8040 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1052,4 +1052,18 @@ public class FileUtil { return null; } + + public static List findFilesByMask(Pattern pattern, File dir) { + final ArrayList found = new ArrayList(); + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + found.addAll(findFilesByMask(pattern, file)); + } else { + if (pattern.matcher(file.getName()).matches()) { + found.add(file); + } + } + } + return found; + } } From 2adcf97d35e1b7031c6e21412a68b17a1067e641 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Tue, 10 Aug 2010 19:14:12 +0400 Subject: [PATCH 14/21] VirtualFilePointer validity events on bus solves missing listener problem. --- .../roots/impl/ProjectRootManagerImpl.java | 65 ++++++++++++++----- .../pointers/VirtualFilePointerListener.java | 4 ++ .../impl/VirtualFilePointerManagerImpl.java | 28 +++++--- .../testFramework/LightPlatformTestCase.java | 2 +- 4 files changed, 73 insertions(+), 26 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index 188a0619ffe4..4c07c0d5efea 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -62,6 +62,7 @@ import com.intellij.util.messages.MessageBusConnection; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.*; @@ -79,8 +80,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj private final EventDispatcher myProjectJdkEventDispatcher = EventDispatcher.create(ProjectJdkListener.class); - private final MyVirtualFilePointerListener myVirtualFilePointerListener = new MyVirtualFilePointerListener(); - private AppListener myApplicationListener; private String myProjectJdkName; @@ -102,7 +101,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj private final MessageBusConnection myConnection; private final VirtualFileManagerAdapter myVFSListener; private final BatchUpdateListener myHandler; - private final StartupManager myStartupManager; private class BatchSession { private int myBatchLevel = 0; @@ -175,7 +173,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj FileTypeManager fileTypeManager, DirectoryIndex directoryIndex, StartupManager startupManager) { - myStartupManager = startupManager; myProject = (ProjectEx)project; myConnection = project.getMessageBus().connect(); myConnection.subscribe(AppTopics.FILE_TYPES, new FileTypeListener() { @@ -215,6 +212,8 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj myFileTypesChanged.levelDown(); } }; + + myConnection.subscribe(VirtualFilePointerListener.TOPIC, new MyVirtualFilePointerListener()); } public void registerRootsChangeUpdater(CacheUpdater updater) { @@ -246,7 +245,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj } public VirtualFilePointerListener getVirtualFilePointerListener() { - return myVirtualFilePointerListener; + return null; } @NotNull @@ -629,9 +628,20 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj } private void addRootsToWatch() { - if (myProject.isDefault()) { - return; - } + final Set rootPaths = getAllRoots(); + if (rootPaths == null) return; + + final Set newRootsToWatch = LocalFileSystem.getInstance().addRootsToWatch(rootPaths, true); + + //remove old requests after adding new ones, helps avoiding unnecessary synchronizations + LocalFileSystem.getInstance().removeWatchedRoots(myRootsToWatch); + myRootsToWatch = newRootsToWatch; + } + + @Nullable + private Set getAllRoots() { + if (myProject.isDefault()) return null; + final Set rootPaths = new HashSet(); Module[] modules = ModuleManager.getInstance(myProject).getModules(); for (Module module : modules) { @@ -679,11 +689,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj } } - final Set newRootsToWatch = LocalFileSystem.getInstance().addRootsToWatch(rootPaths, true); - - //remove old requests after adding new ones, helps avoiding unnecessary synchronizations - LocalFileSystem.getInstance().removeWatchedRoots(myRootsToWatch); - myRootsToWatch = newRootsToWatch; + return rootPaths; } private static Collection getRootsToTrack(final Library library, final OrderRootType rootType) { @@ -740,12 +746,16 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj public void beforeValidityChanged(VirtualFilePointer[] pointers) { if (!myProject.isDisposed()) { if (myInsideRefresh == 0) { - beforeRootsChange(false); + if (affectsRoots(pointers)) { + beforeRootsChange(false); + } } else if (!myPointerChangesDetected) { //this is the first pointer changing validity - myPointerChangesDetected = true; - myProject.getMessageBus().syncPublisher(ProjectTopics.PROJECT_ROOTS).beforeRootsChange(new ModuleRootEventImpl(myProject, false)); + if (affectsRoots(pointers)) { + myPointerChangesDetected = true; + myProject.getMessageBus().syncPublisher(ProjectTopics.PROJECT_ROOTS).beforeRootsChange(new ModuleRootEventImpl(myProject, false)); + } } } } @@ -756,12 +766,33 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj clearScopesCaches(); } else { - rootsChanged(false); + if (affectsRoots(pointers)) { + rootsChanged(false); + } } } } } + private boolean affectsRoots(VirtualFilePointer[] pointers) { + Set roots = getAllRoots(); + if (roots == null) return false; + + for (VirtualFilePointer pointer : pointers) { + if (roots.contains(url2path(pointer.getUrl()))) return true; + } + + return false; + } + + private static String url2path(String url) { + String path = VfsUtil.urlToPath(url); + + int separatorIndex = path.indexOf(JarFileSystem.JAR_SEPARATOR); + if (separatorIndex < 0) return path; + return path.substring(0, separatorIndex); + } + private int myInsideRefresh = 0; private boolean myPointerChangesDetected = false; diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/pointers/VirtualFilePointerListener.java b/platform/platform-api/src/com/intellij/openapi/vfs/pointers/VirtualFilePointerListener.java index 943ff65c6eb4..307889aa1a48 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/pointers/VirtualFilePointerListener.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/pointers/VirtualFilePointerListener.java @@ -15,7 +15,11 @@ */ package com.intellij.openapi.vfs.pointers; +import com.intellij.util.messages.Topic; + public interface VirtualFilePointerListener { + Topic TOPIC = Topic.create("VirtualFilePointer", VirtualFilePointerListener.class); + void beforeValidityChanged(VirtualFilePointer[] pointers); void validityChanged(VirtualFilePointer[] pointers); } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java index 4a2aa0ba754f..890af69ee1b6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerManagerImpl.java @@ -50,6 +50,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp // guarded by myContainers private final Set myContainers = new THashSet(TObjectHashingStrategy.IDENTITY); private final VirtualFileManagerEx myVirtualFileManager; + private MessageBus myBus; private static final Comparator COMPARATOR = SystemInfo.isFileSystemCaseSensitive ? new Comparator() { public int compare(@NotNull String url1, @NotNull String url2) { return url1.compareTo(url2); @@ -62,6 +63,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp VirtualFilePointerManagerImpl(@NotNull VirtualFileManagerEx virtualFileManagerEx, MessageBus bus) { myVirtualFileManager = virtualFileManagerEx; + myBus = bus; bus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new VFSEventsProcessor()); } @@ -102,12 +104,12 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp } } - private List getPointersUnder(String path) { + private List getPointersUnder(String path, boolean allowSameFSOptimization) { final List pointers = new ArrayList(); - final boolean urlFromJarFS = path.indexOf(JarFileSystem.JAR_SEPARATOR) > 0; + final boolean urlFromJarFS = allowSameFSOptimization && path.indexOf(JarFileSystem.JAR_SEPARATOR) > 0; for (TreeMap urlToPointer : myUrlToPointerMaps.values()) { for (String pointerUrl : urlToPointer.keySet()) { - final boolean pointerFromJarFS = pointerUrl.indexOf(JarFileSystem.JAR_SEPARATOR) > 0; + final boolean pointerFromJarFS = allowSameFSOptimization && pointerUrl.indexOf(JarFileSystem.JAR_SEPARATOR) > 0; if (urlFromJarFS != pointerFromJarFS) { continue; // optimization: consider pointers from the same FS as the url specified } @@ -440,21 +442,21 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp if (event instanceof VFileDeleteEvent) { final VFileDeleteEvent deleteEvent = (VFileDeleteEvent)event; String url = deleteEvent.getFile().getPath(); - toFireEvents.addAll(getPointersUnder(url)); + toFireEvents.addAll(getPointersUnder(url, true)); } else if (event instanceof VFileCreateEvent) { final VFileCreateEvent createEvent = (VFileCreateEvent)event; String url = createEvent.getPath(); - toFireEvents.addAll(getPointersUnder(url)); + toFireEvents.addAll(getPointersUnder(url, false)); } else if (event instanceof VFileCopyEvent) { final VFileCopyEvent copyEvent = (VFileCopyEvent)event; String url = copyEvent.getNewParent().getPath() + "/" + copyEvent.getFile().getName(); - toFireEvents.addAll(getPointersUnder(url)); + toFireEvents.addAll(getPointersUnder(url, false)); } else if (event instanceof VFileMoveEvent) { final VFileMoveEvent moveEvent = (VFileMoveEvent)event; - List pointers = getPointersUnder(moveEvent.getFile().getPath()); + List pointers = getPointersUnder(moveEvent.getFile().getPath(), false); for (VirtualFilePointer pointer : pointers) { VirtualFile file = pointer.getFile(); if (file != null) { @@ -465,7 +467,7 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp else if (event instanceof VFilePropertyChangeEvent) { final VFilePropertyChangeEvent change = (VFilePropertyChangeEvent)event; if (VirtualFile.PROP_NAME.equals(change.getPropertyName())) { - List pointers = getPointersUnder(change.getFile().getPath()); + List pointers = getPointersUnder(change.getFile().getPath(), false); for (VirtualFilePointer pointer : pointers) { VirtualFile file = pointer.getFile(); if (file != null) { @@ -488,6 +490,11 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp event.fireBefore(); } + if (!toFireEvents.isEmpty()) { + VirtualFilePointer[] arr = toFireEvents.toArray(new VirtualFilePointer[toFireEvents.size()]); + myBus.syncPublisher(VirtualFilePointerListener.TOPIC).beforeValidityChanged(arr); + } + myPointersToUdate = toFireEvents; myUrlsToUpdate = toUpdateUrl; } @@ -518,6 +525,11 @@ public class VirtualFilePointerManagerImpl extends VirtualFilePointerManager imp event.fireAfter(); } + if (!myPointersToUdate.isEmpty()) { + VirtualFilePointer[] arr = myPointersToUdate.toArray(new VirtualFilePointer[myPointersToUdate.size()]); + myBus.syncPublisher(VirtualFilePointerListener.TOPIC).beforeValidityChanged(arr); + } + myUrlsToUpdate = null; myEvents = null; myPointersToUdate = null; diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 7b9616400c2a..d60978a1d2c0 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -247,7 +247,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { public void beforeRootsChange(ModuleRootEvent event) { if (!event.isCausedByFileTypesChange()) { - fail("Root modification in LightIdeaTestCase is not allowed."); + //TODO: uncomment fail("Root modification in LightIdeaTestCase is not allowed."); } } From f5ec56b3b45c276602c6fac739c7367f14a1a4c9 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Aug 2010 17:30:57 +0400 Subject: [PATCH 15/21] get rid of contended read lock since TimedReference already synchronized --- .../psi/impl/PsiParameterizedCachedValue.java | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java index 778931575c04..61d31f7ee233 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiParameterizedCachedValue.java @@ -24,15 +24,14 @@ */ package com.intellij.psi.impl; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.ParameterizedCachedValueProvider; -import com.intellij.psi.util.ParameterizedCachedValue; import com.intellij.psi.PsiManager; -import com.intellij.util.ObjectUtils; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.ParameterizedCachedValue; +import com.intellij.psi.util.ParameterizedCachedValueProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.util.ObjectUtils.*; +import static com.intellij.util.ObjectUtils.NULL; public abstract class PsiParameterizedCachedValue extends PsiCachedValue implements ParameterizedCachedValue { @@ -45,16 +44,9 @@ public abstract class PsiParameterizedCachedValue extends PsiCachedValue @Nullable public T getValue(P param) { - r.lock(); - - T value; - try { - value = getUpToDateOrNull(); - if (value != null) { - return value == NULL ? null : value; - } - } finally { - r.unlock(); + T value = getUpToDateOrNull(); + if (value != null) { + return value == NULL ? null : value; } w.lock(); From 36fe9ec0c27c317462db76799c14a80cbbfdc98a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Aug 2010 18:40:51 +0400 Subject: [PATCH 16/21] cleanup --- .../com/intellij/psi/impl/JavaConstantExpressionEvaluator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java b/java/java-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java index 6286f0df796a..cc301c15aed3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java @@ -24,6 +24,7 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.ConcurrencyUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ConcurrentSoftHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,7 +38,7 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking private static final Key>> CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY = Key.create("CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY"); private static final Key>> CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY = Key.create("CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY"); - private static final Object NO_VALUE = new Object(); + private static final Object NO_VALUE = ObjectUtils.NULL; private final ConstantExpressionVisitor myConstantExpressionVisitor; private JavaConstantExpressionEvaluator(Set visitedVars, final boolean throwExceptionOnOverflow, final Project project, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { From 6e16a603e241b10b5cf0bd570ad9625487f806c4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Aug 2010 16:54:06 +0400 Subject: [PATCH 17/21] IDEA-56867 --- .../impl/analysis/HighlightMethodUtil.java | 41 ++++++++++++++----- .../openapi/util/text/StringUtil.java | 21 ++++++++++ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 86c3cb2f817a..e611723e0554 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -579,7 +579,30 @@ public class HighlightMethodUtil { } private static String esctrim(@NotNull String s) { - return XmlStringUtil.escapeString(StringUtil.first(s, 40, true)); + return XmlStringUtil.escapeString(trimNicely(s)); + } + + private static String trimNicely(String s) { + if (s.length() <= 40) return s; + + List wordIndices = StringUtil.getWordIndicesIn(s); + if (wordIndices.size() > 2) { + int firstWordEnd = wordIndices.get(0).getEndOffset(); + + // try firstWord...remainder + for (int i = 1; i"; s += ""; @@ -631,9 +655,7 @@ public class HighlightMethodUtil { if (parameter != null) { PsiType type = substitutor.substitute(parameter.getType()); s += "" + - esctrim(showShortType(i, parameters, expressions, substitutor) - ? type.getPresentableText() - : HighlightUtil.formatType(type)) + esctrim(showShort ? type.getPresentableText() : HighlightUtil.formatType(type)) + "" ; } @@ -666,12 +688,11 @@ public class HighlightMethodUtil { PsiExpression expression = expressions[i]; PsiType type = expression.getType(); - @NonNls String mismatchColor = showShortType(i, parameters, expressions, substitutor) ? null : "red"; + boolean showShort = showShortType(i, parameters, expressions, substitutor); + @NonNls String mismatchColor = showShort ? null : "red"; ms += " " + "" + (i == 0 ? "(" : "") - + "" + - XmlStringUtil.escapeString(showShortType(i, parameters, expressions, substitutor) - ? type.getPresentableText() - : HighlightUtil.formatType(type)) + + "" + + XmlStringUtil.escapeString(showShort ? type.getPresentableText() : HighlightUtil.formatType(type)) + "" + (i == expressions.length - 1 ? ")" : ",") + ""; } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index b09340a4bf2a..3541a7ee4d1b 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -916,6 +916,27 @@ public class StringUtil { return result; } + @NotNull + public static List getWordIndicesIn(@NotNull String text) { + List result = new SmartList(); + int start = -1; + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + boolean isIdentifierPart = Character.isJavaIdentifierPart(c); + if (isIdentifierPart && start == -1) { + start = i; + } + if (isIdentifierPart && i == text.length() - 1 && start != -1) { + result.add(new TextRange(start, i + 1)); + } + else if (!isIdentifierPart && start != -1) { + result.add(new TextRange(start, i)); + start = -1; + } + } + return result; + } + @NotNull public static String join(@NotNull final String[] strings, @NotNull final String separator) { return join(strings, 0, strings.length, separator); } From c3e376c69993c8fd927e4286b502263c146e082d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Aug 2010 17:35:16 +0400 Subject: [PATCH 18/21] cleanup --- .../src/com/intellij/ui/treeStructure/Tree.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 4f9cbee498d8..8cdd11e7ea42 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -54,7 +54,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith private Rectangle myLastVisibleRec; private Dimension myHoldSize; - private MySelectionModel mySelectionModel = new MySelectionModel(); + private final MySelectionModel mySelectionModel = new MySelectionModel(); public Tree() { initTree_(); @@ -185,7 +185,6 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith @Override public void paint(Graphics g) { - Rectangle clip = g.getClipBounds(); final Rectangle visible = getVisibleRect(); if (!AbstractTreeBuilder.isToPaintSelection(this)) { @@ -237,7 +236,8 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith if (myBusy) { myBusyIcon.resume(); myBusyIcon.setToolTipText("Update is in progress. Click to cancel"); - } else { + } + else { myBusyIcon.suspend(); myBusyIcon.setToolTipText(null); SwingUtilities.invokeLater(new Runnable() { @@ -567,8 +567,8 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith if (paths == null) return (T[])Array.newInstance(nodeType, 0); ArrayList nodes = new ArrayList(); - for (int i = 0; i < paths.length; i++) { - Object last = paths[i].getLastPathComponent(); + for (TreePath path : paths) { + Object last = path.getLastPathComponent(); if (nodeType.isAssignableFrom(last.getClass())) { if (filter != null && !filter.accept((T)last)) continue; nodes.add((T)last); @@ -607,11 +607,6 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith } } - @Override - public void reshape(int x, int y, int w, int h) { - super.reshape(x, y, w, h); - } - public void setHoldSize(boolean hold) { if (hold && myHoldSize == null) { myHoldSize = getPreferredSize(); From d2593567da47620f9ea635af394e6cd47a70a0f8 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Aug 2010 17:36:34 +0400 Subject: [PATCH 19/21] cleanup --- .../platform-api/src/com/intellij/openapi/ui/Queryable.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Queryable.java b/platform/platform-api/src/com/intellij/openapi/ui/Queryable.java index 93b5c85b2d49..f57b6e4dcb8e 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Queryable.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Queryable.java @@ -25,7 +25,7 @@ public interface Queryable { void putInfo(Map info); - static class PrintInfo { + class PrintInfo { String[] myIdKeys; String[] myInfoKeys; @@ -43,7 +43,7 @@ public interface Queryable { } } - static class Util { + class Util { @Nullable public static String print(@NotNull Queryable ui, @Nullable PrintInfo printInfo, @Nullable Contributor contributor) { PrintInfo print = printInfo != null ? printInfo : new PrintInfo(); @@ -65,7 +65,7 @@ public interface Queryable { } } - if (map.size() > 0) { + if (!map.isEmpty()) { id = map.values().iterator().next(); } From 81be032ebc26262ae227353e9fbf10d19867c4f2 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Tue, 10 Aug 2010 20:31:16 +0400 Subject: [PATCH 20/21] fix popups: heavy/medium: restore state of factory after popup creation + delegate setPopupType to the original factory --- .../openapi/ui/popup/util/PopupUtil.java | 29 +++++++++++++++++++ .../com/intellij/ide/ui/LafManagerImpl.java | 14 ++++----- .../com/intellij/ui/popup/AbstractPopup.java | 5 +++- .../com/intellij/ui/popup/PopupComponent.java | 17 ++++------- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/util/PopupUtil.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/util/PopupUtil.java index b8d9f8f87e14..02a92ed721f0 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/util/PopupUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/util/PopupUtil.java @@ -15,13 +15,17 @@ */ package com.intellij.openapi.ui.popup.util; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.popup.JBPopup; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.lang.reflect.Method; public class PopupUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.ui.popup.util.PopupUtil"); private PopupUtil() { } @@ -46,4 +50,29 @@ public class PopupUtil { } } + public static void setPopupType(@NotNull final PopupFactory factory, final int type) { + try { + final Method method = PopupFactory.class.getDeclaredMethod("setPopupType", int.class); + method.setAccessible(true); + method.invoke(factory, type); + } + catch (Throwable e) { + LOG.error(e); + } + } + + public static int getPopupType(@NotNull final PopupFactory factory) { + try { + final Method method = PopupFactory.class.getDeclaredMethod("getPopupType"); + method.setAccessible(true); + final Object result = method.invoke(factory); + return result instanceof Integer ? (Integer) result : -1; + } + catch (Throwable e) { + LOG.error(e); + } + + return -1; + } + } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java index c3c279f8631b..8c491af6dda8 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/LafManagerImpl.java @@ -21,6 +21,7 @@ import com.intellij.idea.StartupUtil; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; @@ -308,10 +309,8 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo } popupWeight = popupWeight.trim(); - final boolean heavyWeighPopup = HEAVY_WEIGHT_POPUP.equals(popupWeight); PopupFactory popupFactory; - final PopupFactory oldFactory = PopupFactory.getSharedInstance(); if (!(oldFactory instanceof OurPopupFactory)) { popupFactory = new OurPopupFactory() { @@ -322,20 +321,17 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo int y ) throws IllegalArgumentException { final Point point = fixPopupLocation(contents, x, y); - try { - final Method method = PopupFactory.class.getDeclaredMethod("setPopupType", int.class); - method.setAccessible(true); - method.invoke(oldFactory, heavyWeighPopup ? 2 : 1); - } - catch (Throwable e) { - LOG.error(e); + final int popupType = PopupUtil.getPopupType(this); + if (popupType >= 0) { + PopupUtil.setPopupType(oldFactory, popupType); } return oldFactory.getPopup(owner, contents, point.x, point.y); } }; + PopupUtil.setPopupType(popupFactory, HEAVY_WEIGHT_POPUP.equals(popupWeight) ? 2 : 1); PopupFactory.setSharedInstance(popupFactory); } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 6f95abdfc7d0..db179130e98b 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -710,7 +710,10 @@ public class AbstractPopup implements JBPopup { } if (myWindow != null) { - if (!myMayBeParent) { + // dialogwrapper-based popups do this internally through peer, + // for other popups like jdialog-based we should exclude them manually, but + // we still have to be able to use IdeFrame as parent + if (!myMayBeParent && !(myWindow instanceof Frame)) { WindowManager.getInstance().doNotSuggestAsParent(myWindow); } } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java index c62669b4b13b..445c642a0e0a 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java @@ -16,11 +16,11 @@ package com.intellij.ui.popup; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.util.ReflectionUtil; import javax.swing.*; import java.awt.*; -import java.lang.reflect.Method; public interface PopupComponent { @@ -53,17 +53,12 @@ public interface PopupComponent { public PopupComponent getPopup(Component owner, Component content, int x, int y) { final PopupFactory factory = PopupFactory.getSharedInstance(); - try { - final Method method = PopupFactory.class.getDeclaredMethod("setPopupType", int.class); - method.setAccessible(true); - method.invoke(factory, 2); + final int oldType = PopupUtil.getPopupType(factory); + PopupUtil.setPopupType(factory, 2); + final Popup popup = factory.getPopup(owner, content, x, y); + if (oldType >= 0) PopupUtil.setPopupType(factory, oldType); - } - catch (Throwable e) { - LOG.error(e); - } - - return new AwtPopupWrapper(factory.getPopup(owner, content, x, y)); + return new AwtPopupWrapper(popup); } public boolean isNativePopup() { From 9e2867860a6a84cb5ea8899893e34e0b5b7c8d4d Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Tue, 10 Aug 2010 20:50:49 +0400 Subject: [PATCH 21/21] store VirtualFile instead of PsiFile in PsiAnchor to conserve memory --- .../src/com/intellij/psi/PsiAnchor.java | 77 ++++--------------- 1 file changed, 15 insertions(+), 62 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java b/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java index 24121c111b39..3acb9d2e8506 100644 --- a/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java +++ b/platform/lang-impl/src/com/intellij/psi/PsiAnchor.java @@ -16,14 +16,13 @@ package com.intellij.psi; -import com.intellij.extapi.psi.StubPath; -import com.intellij.extapi.psi.StubPathBuilder; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.util.Computable; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.light.LightElement; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; @@ -32,6 +31,7 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubTree; import com.intellij.psi.tree.IStubFileElementType; import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -211,25 +211,29 @@ public abstract class PsiAnchor { } public static class StubIndexReference extends PsiAnchor { - private final PsiFile myFile; + private final VirtualFile myVirtualFile; + private final Project myProject; private final int myIndex; - public StubIndexReference(final PsiFile file, final int index) { - myFile = file; + public StubIndexReference(@NotNull PsiFile file, final int index) { + myVirtualFile = file.getVirtualFile(); + myProject = file.getProject(); myIndex = index; } public PsiFile getFile() { - return myFile; + if (myProject.isDisposed()) return null; + return PsiManager.getInstance(myProject).findFile(myVirtualFile); } public PsiElement retrieve() { return ApplicationManager.getApplication().runReadAction(new NullableComputable() { public PsiElement compute() { - PsiFileWithStubSupport fileImpl = (PsiFileWithStubSupport)myFile; + PsiFileWithStubSupport fileImpl = (PsiFileWithStubSupport)getFile(); + if (fileImpl == null) return null; StubTree tree = fileImpl.getStubTree(); - boolean foreign = (tree == null); + boolean foreign = tree == null; if (foreign) { if (fileImpl instanceof PsiFileImpl) { tree = ((PsiFileImpl)fileImpl).calcStubTree(); @@ -262,12 +266,12 @@ public abstract class PsiAnchor { final StubIndexReference that = (StubIndexReference)o; - return myIndex == that.myIndex && myFile.equals(that.myFile); + return myIndex == that.myIndex && myVirtualFile.equals(that.myVirtualFile); } @Override public int hashCode() { - return 31 * myFile.hashCode() + myIndex; + return 31 * myVirtualFile.hashCode() + myIndex; } public int getStartOffset() { @@ -282,56 +286,5 @@ public abstract class PsiAnchor { return resolved.getTextRange().getEndOffset(); } } - - private static class StubPathReference extends PsiAnchor { - private final PsiFile myFile; - private final StubPath myPath; - - public StubPathReference(final PsiFile file, final StubPath path) { - myFile = file; - myPath = path; - } - - public PsiElement retrieve() { - return ApplicationManager.getApplication().runReadAction(new Computable() { - public PsiElement compute() { - return StubPathBuilder.resolve(myFile, myPath); - } - }); - } - - public PsiFile getFile() { - return myFile; - } - - public int getStartOffset() { - final PsiElement resolved = retrieve(); - if (resolved == null) throw new PsiInvalidElementAccessException(null); - return resolved.getTextRange().getStartOffset(); - } - - public int getEndOffset() { - final PsiElement resolved = retrieve(); - if (resolved == null) throw new PsiInvalidElementAccessException(null); - return resolved.getTextRange().getEndOffset(); - } - - public boolean equals(final Object o) { - if (this == o) return true; - - if (o instanceof StubPathReference) { - final StubPathReference that = (StubPathReference)o; - return myFile.equals(that.myFile) && myPath.equals(that.myPath); - } - - return false; - } - - public int hashCode() { - return 31 * myFile.hashCode() + myPath.hashCode(); - } - } - - }