From e26b7ebd04509dd6752943a1b2e1c2151c6e57bf Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Fri, 18 May 2012 12:53:44 +0400 Subject: [PATCH 1/6] IDEA-19061 Integrate the Rearranger-plugin into core-IDEA *) test DSL for the field type and method return type has been added; *) more tests have been refactored and enabled; --- .../com/wrq/rearranger/entry/MethodEntry.java | 8 +- .../settings/RearrangerSettings.java | 30 +++---- .../com/wrq/rearranger/RearrangerTest.groovy | 82 ++++++++++--------- .../rearranger/util/RearrangerTestDsl.java | 2 + .../util/java/JavaFieldRuleBuilder.groovy | 1 + .../util/java/JavaMethodRuleBuilder.groovy | 1 + .../OpsBlockingQueueIndentedResult.java | 11 +-- .../wrq/rearranger/RearrangementResult12.java | 5 +- 8 files changed, 71 insertions(+), 69 deletions(-) diff --git a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java index 7826d6946b24..4734ba867a2b 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java +++ b/plugins/rearranger/src/com/wrq/rearranger/entry/MethodEntry.java @@ -1050,11 +1050,9 @@ public class MethodEntry extends ClassContentsEntry implements RelatableEntry { return; } createAlternateValueString(); - /** - * we don't want to check for comments in the body of the method. So reduce the alternate value string - * to only that text up to and including the open brace. Temporarily remove the rest of the text; append - * it again after checking for comments. - */ + // We don't want to check for comments in the body of the method. So reduce the alternate value string + // to only that text up to and including the open brace. Temporarily remove the rest of the text; append + // it again after checking for comments. int brace = myAlternateValue.indexOf('{'); String temp = ""; if (brace >= 0) { diff --git a/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java b/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java index 632e3f81788c..786676f8d68b 100644 --- a/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java +++ b/plugins/rearranger/src/com/wrq/rearranger/settings/RearrangerSettings.java @@ -361,7 +361,7 @@ public final class RearrangerSettings { // Level 2 methods public void setGlobalCommentPattern(String globalCommentPattern) { - this.myGlobalCommentPattern = globalCommentPattern; + myGlobalCommentPattern = globalCommentPattern; } // end of Level 2 methods @@ -384,7 +384,7 @@ public final class RearrangerSettings { // Level 2 methods public void setOverloadedOrder(int overloadedOrder) { - this.myOverloadedOrder = overloadedOrder; + myOverloadedOrder = overloadedOrder; } // end of Level 2 methods @@ -403,7 +403,7 @@ public final class RearrangerSettings { // Level 2 methods public void setAskBeforeRearranging(boolean askBeforeRearranging) { - this.myAskBeforeRearranging = askBeforeRearranging; + myAskBeforeRearranging = askBeforeRearranging; } public boolean isKeepGettersSettersTogether() { @@ -413,7 +413,7 @@ public final class RearrangerSettings { // Level 2 methods public void setKeepGettersSettersTogether(boolean keepGettersSettersTogether) { - this.myKeepGettersSettersTogether = keepGettersSettersTogether; + myKeepGettersSettersTogether = keepGettersSettersTogether; } public boolean isKeepGettersSettersWithProperty() { @@ -421,7 +421,7 @@ public final class RearrangerSettings { } public void setKeepGettersSettersWithProperty(boolean keepGettersSettersWithProperty) { - this.myKeepGettersSettersWithProperty = keepGettersSettersWithProperty; + myKeepGettersSettersWithProperty = keepGettersSettersWithProperty; } // end of Level 2 methods // end of Level 1 methods @@ -434,7 +434,7 @@ public final class RearrangerSettings { // Level 2 methods public void setKeepOverloadedMethodsTogether(boolean keepOverloadedMethodsTogether) { - this.myKeepOverloadedMethodsTogether = keepOverloadedMethodsTogether; + myKeepOverloadedMethodsTogether = keepOverloadedMethodsTogether; } // end of Level 2 methods @@ -445,7 +445,7 @@ public final class RearrangerSettings { } public void setRearrangeInnerClasses(boolean rearrangeInnerClasses) { - this.myRearrangeInnerClasses = rearrangeInnerClasses; + myRearrangeInnerClasses = rearrangeInnerClasses; } // end of Level 2 methods @@ -459,7 +459,7 @@ public final class RearrangerSettings { // Level 2 methods public void setRemoveBlanksInsideCodeBlocks(boolean removeBlanksInsideCodeBlocks) { - this.myRemoveBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks; + myRemoveBlanksInsideCodeBlocks = removeBlanksInsideCodeBlocks; } public boolean isShowComments() { @@ -467,7 +467,7 @@ public final class RearrangerSettings { } public void setShowComments(boolean showComments) { - this.myShowComments = showComments; + myShowComments = showComments; } // end of Level 2 methods @@ -481,7 +481,7 @@ public final class RearrangerSettings { // Level 2 methods public void setShowFields(boolean showFields) { - this.myShowFields = showFields; + myShowFields = showFields; } public boolean isShowMatchedRules() { @@ -489,7 +489,7 @@ public final class RearrangerSettings { } public void setShowMatchedRules(boolean showMatchedRules) { - this.myShowMatchedRules = showMatchedRules; + myShowMatchedRules = showMatchedRules; } public boolean isShowParameterNames() { @@ -499,7 +499,7 @@ public final class RearrangerSettings { // Level 2 methods public void setShowParameterNames(boolean showParameterNames) { - this.myShowParameterNames = showParameterNames; + myShowParameterNames = showParameterNames; } // end of Level 2 methods @@ -513,7 +513,7 @@ public final class RearrangerSettings { // Level 2 methods public void setShowParameterTypes(boolean showParameterTypes) { - this.myShowParameterTypes = showParameterTypes; + myShowParameterTypes = showParameterTypes; } // end of Level 2 methods @@ -524,7 +524,7 @@ public final class RearrangerSettings { } public void setShowRules(boolean showRules) { - this.myShowRules = showRules; + myShowRules = showRules; } // end of Level 2 methods @@ -534,7 +534,7 @@ public final class RearrangerSettings { } public void setShowTypeAfterMethod(boolean showTypeAfterMethod) { - this.myShowTypeAfterMethod = showTypeAfterMethod; + myShowTypeAfterMethod = showTypeAfterMethod; } // ------------------------ CANONICAL METHODS ------------------------ diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy index 07f2c8ff1fda..7dfdf2233035 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/RearrangerTest.groovy @@ -160,15 +160,13 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { testOpsBlockingQueueExampleWorker(false, "OpsBlockingQueue", false, "OpsBlockingQueue"); } -// public final void testOpsBlockingQueueExampleWithGlobalPattern() throws Exception { -// testOpsBlockingQueueExampleWorker(true, "/com/wrq/rearranger/OpsBlockingQueue.java", -// false, "/com/wrq/rearranger/OpsBlockingQueue.java"); -// } -// -// public final void testOpsBlockingQueueExampleWithIndentedComments() throws Exception { -// testOpsBlockingQueueExampleWorker(false, "/com/wrq/rearranger/OpsBlockingQueueIndented.java", -// true, "/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java"); -// } + public final void testOpsBlockingQueueExampleWithGlobalPattern() throws Exception { + testOpsBlockingQueueExampleWorker(true, "OpsBlockingQueue", false, "OpsBlockingQueue"); + } + + public final void testOpsBlockingQueueExampleWithIndentedComments() throws Exception { + testOpsBlockingQueueExampleWorker(false, "OpsBlockingQueueIndented", true, "OpsBlockingQueueIndentedResult"); + } private void testOpsBlockingQueueExampleWorker(boolean doGlobalPattern, String srcFilename, @@ -294,36 +292,42 @@ class RearrangerTest extends LightCodeInsightFixtureTestCase { } } -// public final void testReturnTypeMatch() throws Exception { -// configureByFile("/com/wrq/rearranger/RearrangementTest12.java"); -// final PsiFile file = getFile(); -// final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); -// MethodAttributes ma; -// ma = new MethodAttributes(); -// ma.getReturnTypeAttr().setMatch(true); -// ma.getReturnTypeAttr().setExpression("void"); -// rs.addItem(ma, 0); -// FieldAttributes fa = new FieldAttributes(); -// fa.getTypeAttr().setMatch(true); -// fa.getTypeAttr().setExpression("int"); -// rs.addItem(fa, 1); -// ma = new MethodAttributes(); -// ma.getReturnTypeAttr().setMatch(true); -// ma.getReturnTypeAttr().setExpression(".*je.*"); -// rs.addItem(ma, 2); -// ma = new MethodAttributes(); -// ma.getReturnTypeAttr().setMatch(true); -// ma.getReturnTypeAttr().setExpression("Integer\\[\\]"); -// rs.addItem(ma, 3); -// ma = new MethodAttributes(); -// ma.getReturnTypeAttr().setMatch(true); -// ma.getReturnTypeAttr().setExpression("int"); -// rs.addItem(ma, 4); -// final RearrangerActionHandler rah = new RearrangerActionHandler(); -// rah.rearrangeDocument(getProject(), file, rs, doc); -// super.checkResultByFile("/com/wrq/rearranger/RearrangementResult12.java"); -// } -// + public final void testReturnTypeMatch() throws Exception { + doTest('RearrangementTest12', 'RearrangementResult12') { + methodRule.create { returnType( 'void' ) } + fieldRule.create { type( 'int' ) } + methodRule.create { returnType( '.*je.*' ) } + methodRule.create { returnType( /Integer\[\]/) } + methodRule.create { returnType( 'int' ) } + } + + + //MethodAttributes ma; + //ma = new MethodAttributes(); + //ma.getReturnTypeAttr().setMatch(true); + //ma.getReturnTypeAttr().setExpression("void"); + //rs.addItem(ma, 0); + //FieldAttributes fa = new FieldAttributes(); + //fa.getTypeAttr().setMatch(true); + //fa.getTypeAttr().setExpression("int"); + //rs.addItem(fa, 1); + //ma = new MethodAttributes(); + //ma.getReturnTypeAttr().setMatch(true); + //ma.getReturnTypeAttr().setExpression(".*je.*"); + //rs.addItem(ma, 2); + //ma = new MethodAttributes(); + //ma.getReturnTypeAttr().setMatch(true); + //ma.getReturnTypeAttr().setExpression("Integer\\[\\]"); + //rs.addItem(ma, 3); + //ma = new MethodAttributes(); + //ma.getReturnTypeAttr().setMatch(true); + //ma.getReturnTypeAttr().setExpression("int"); + //rs.addItem(ma, 4); + //final RearrangerActionHandler rah = new RearrangerActionHandler(); + //rah.rearrangeDocument(getProject(), file, rs, doc); + //super.checkResultByFile("/com/wrq/rearranger/RearrangementResult12.java"); + } + // public final void testRelatedMethodsDepthOriginal() throws Exception { // configureByFile("/com/wrq/rearranger/RearrangementTest13.java"); // final PsiFile file = getFile(); diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/util/RearrangerTestDsl.java b/plugins/rearranger/test/src/com/wrq/rearranger/util/RearrangerTestDsl.java index 58a58b7ac408..ab7ae00aa5f3 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/util/RearrangerTestDsl.java +++ b/plugins/rearranger/test/src/com/wrq/rearranger/util/RearrangerTestDsl.java @@ -16,6 +16,8 @@ public enum RearrangerTestDsl { INITIALIZER, /** Method target type (e.g. constructor). */ TARGET, + TYPE, + RETURN_TYPE("returnType"), SORT, COMMENT, diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaFieldRuleBuilder.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaFieldRuleBuilder.groovy index d093c65bb0d9..13d5f2865b8c 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaFieldRuleBuilder.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaFieldRuleBuilder.groovy @@ -14,6 +14,7 @@ class JavaFieldRuleBuilder extends AbstractJavaRuleBuilder { { def handlers = [(InitializerType.ANONYMOUS_CLASS) : createBooleanAttributeHandler('initialisedByAnonymousClassAttr')] registerHandler(RearrangerTestDsl.INITIALIZER, { data, attributes, rule -> handlers[data](attributes, rule) }) + registerHandler(RearrangerTestDsl.TYPE, createStringAttributeHandler('typeAttr')) } @Override diff --git a/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaMethodRuleBuilder.groovy b/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaMethodRuleBuilder.groovy index 68fdece9d412..a59998417dc6 100644 --- a/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaMethodRuleBuilder.groovy +++ b/plugins/rearranger/test/src/com/wrq/rearranger/util/java/JavaMethodRuleBuilder.groovy @@ -18,6 +18,7 @@ class JavaMethodRuleBuilder extends AbstractJavaRuleBuilder { (MethodType.OTHER) : createRawBooleanAttributeHandler('otherMethodType') ] registerHandler(RearrangerTestDsl.TARGET, { data, attributes, rule -> handlers[data](attributes, rule) }) + registerHandler(RearrangerTestDsl.RETURN_TYPE, createStringAttributeHandler('returnTypeAttr')) } @Override diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java index a8ba010d2f51..fcda3831105d 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/OpsBlockingQueueIndentedResult.java @@ -10,22 +10,20 @@ import opsx.server.email.OpsEmailGenerator; /** @author dchan */ public class OpsBlockingQueue extends OpsNonBlockingQueue { - //*********************************** PROTECTED/PACKAGE FIELDS ************************************** +//*********************************** PROTECTED/PACKAGE FIELDS ************************************** protected final Object putLock; protected final Object takeLock; protected volatile int waitCount; - //************************************** PRIVATE FIELDS ***************************************** +//************************************** PRIVATE FIELDS ***************************************** private static final OpsLogCategory logCat = (OpsLogCategory)OpsLogCategory.getInstance(OpsEmailGenerator.class); //************************************** CONSTRUCTORS ************************************* - /** Creates new OpsBlockingQueue */ public OpsBlockingQueue() { takeLock = new Object(); putLock = new Object(); waitCount = 0; } - - //************************************** PUBLIC METHODS ************************************* +//************************************** PUBLIC METHODS ************************************* // PUBLIC METHODS LINE 2 public void put(Object obj) { synchronized (putLock) { @@ -61,8 +59,7 @@ public class OpsBlockingQueue extends OpsNonBlockingQueue { } } } - - //********************************* PACKAGE/PROTECTED METHODS ******************************** +//********************************* PACKAGE/PROTECTED METHODS ******************************** protected Object takeNext() { synchronized (takeLock) { return super.takeNext(); diff --git a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java index fdcee3db5fb1..096c4c224c67 100644 --- a/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java +++ b/plugins/rearranger/test/testData/com/wrq/rearranger/RearrangementResult12.java @@ -1,9 +1,9 @@ class RearrangementTest12 { + void method(int y) { x = y; } - - int x; + int x; Object convertX() { return new Integer(x); @@ -16,6 +16,5 @@ class RearrangementTest12 { int getX() { return x; } - String s; } \ No newline at end of file From 9ec6ae66d199d2ba44274b6b4c26e39273dc46be Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 18 May 2012 13:16:48 +0400 Subject: [PATCH 2/6] non-negative range asserted --- .../intellij/codeInsight/editorActions/moveUpDown/LineRange.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-api/src/com/intellij/codeInsight/editorActions/moveUpDown/LineRange.java b/platform/lang-api/src/com/intellij/codeInsight/editorActions/moveUpDown/LineRange.java index 0b58917e447e..b9fba8d2bf57 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/editorActions/moveUpDown/LineRange.java +++ b/platform/lang-api/src/com/intellij/codeInsight/editorActions/moveUpDown/LineRange.java @@ -33,6 +33,7 @@ public class LineRange { public LineRange(final int startLine, final int endLine) { this.startLine = startLine; this.endLine = endLine; + LOG.assertTrue(startLine > 0, "Negative start line"); if (startLine > endLine) { LOG.error("start > end: start=" + startLine+"; end="+endLine); } From f54664873f2a3ba959f33529d6b9d3faba850aaa Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 18 May 2012 11:42:31 +0200 Subject: [PATCH 3/6] rationalize static --- .../src/com/intellij/ide/macro/FilePackageMacro.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/macro/FilePackageMacro.java b/java/java-impl/src/com/intellij/ide/macro/FilePackageMacro.java index 96343c638664..e744e7cbed8e 100644 --- a/java/java-impl/src/com/intellij/ide/macro/FilePackageMacro.java +++ b/java/java-impl/src/com/intellij/ide/macro/FilePackageMacro.java @@ -17,7 +17,7 @@ package com.intellij.ide.macro; import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.DataKeys; +import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.psi.JavaDirectoryService; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; @@ -41,7 +41,7 @@ public final class FilePackageMacro extends Macro { @Nullable static PsiPackage getFilePackage(DataContext dataContext) { - PsiFile psiFile = DataKeys.PSI_FILE.getData(dataContext); + PsiFile psiFile = LangDataKeys.PSI_FILE.getData(dataContext); if (psiFile == null) return null; PsiDirectory containingDirectory = psiFile.getContainingDirectory(); if (containingDirectory == null || !containingDirectory.isValid()) return null; From 6f87f80349abb12ba21c073ed1cb163e951bc05d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 18 May 2012 12:18:52 +0200 Subject: [PATCH 4/6] fix data context assertions from macro --- .../com/intellij/ide/macro/MacroManager.java | 12 ++-- .../com/intellij/tools/HackyDataContext.java | 59 +++++++++++++++++++ .../src/com/intellij/tools/ToolAction.java | 3 +- .../com/intellij/tools/ToolRunProfile.java | 12 ++-- .../intellij/ide/impl/DataManagerImpl.java | 10 ++-- .../keymap/impl/IdeKeyEventDispatcher.java | 2 +- .../ant/config/actions/TargetActionStub.java | 15 ++--- 7 files changed, 84 insertions(+), 29 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/tools/HackyDataContext.java diff --git a/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java b/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java index 24f36789170f..567f9728e1ad 100644 --- a/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java +++ b/platform/lang-impl/src/com/intellij/ide/macro/MacroManager.java @@ -18,8 +18,6 @@ package com.intellij.ide.macro; import com.intellij.application.options.PathMacrosImpl; import com.intellij.ide.DataManager; -import com.intellij.ide.IdeEventQueue; -import com.intellij.ide.impl.DataManagerImpl; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.components.ServiceManager; @@ -147,11 +145,11 @@ public final class MacroManager { String name = "$" + macro.getName() + "$"; if (str.indexOf(name) >= 0) { String expanded = macro.expand(dataContext); - if (dataContext instanceof DataManagerImpl.MyDataContext) { - // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext - // since we know exactly that context is valid, we need to update its event count - ((DataManagerImpl.MyDataContext)dataContext).setEventCount(IdeEventQueue.getInstance().getEventCount()); - } + //if (dataContext instanceof DataManagerImpl.MyDataContext) { + // // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext + // // since we know exactly that context is valid, we need to update its event count + // ((DataManagerImpl.MyDataContext)dataContext).setEventCount(IdeEventQueue.getInstance().getEventCount()); + //} if (expanded == null) { expanded = ""; } diff --git a/platform/lang-impl/src/com/intellij/tools/HackyDataContext.java b/platform/lang-impl/src/com/intellij/tools/HackyDataContext.java new file mode 100644 index 000000000000..4b18c01c71f9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/tools/HackyDataContext.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.tools; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.DataKey; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import org.jetbrains.annotations.NonNls; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author Konstantin Bulenkov + */ +class HackyDataContext implements DataContext { + private static DataKey[] keys = { + PlatformDataKeys.PROJECT, + PlatformDataKeys.PROJECT_FILE_DIRECTORY, + PlatformDataKeys.EDITOR, + PlatformDataKeys.VIRTUAL_FILE, + LangDataKeys.MODULE, + LangDataKeys.PSI_FILE + }; + + + private final Map values = new HashMap(); + + public HackyDataContext(DataContext context) { + for (DataKey key : keys) { + values.put(key.getName(), key.getData(context)); + } + } + + @Override + public Object getData(@NonNls String dataId) { + if (values.keySet().contains(dataId)) { + return values.get(dataId); + } + //noinspection UseOfSystemOutOrSystemErr + System.out.println("Please add " + dataId + " key in " + getClass().getName()); + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/tools/ToolAction.java b/platform/lang-impl/src/com/intellij/tools/ToolAction.java index 2c5e975b4225..8417b1f7ade5 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolAction.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolAction.java @@ -35,10 +35,11 @@ public class ToolAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { MacroManager.getInstance().cacheMacrosPreview(e.getDataContext()); + final HackyDataContext dataContext = new HackyDataContext(e.getDataContext()); Tool[] tools = ToolManager.getInstance().getTools(); for (Tool tool : tools) { if (myActionId.equals(tool.getActionId())) { - tool.execute(e.getDataContext()); + tool.execute(dataContext); break; } } diff --git a/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java b/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java index e14eff7e9577..a257e0683989 100644 --- a/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java +++ b/platform/lang-impl/src/com/intellij/tools/ToolRunProfile.java @@ -28,8 +28,6 @@ import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.process.ProcessTerminatedListener; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; -import com.intellij.ide.IdeEventQueue; -import com.intellij.ide.impl.DataManagerImpl; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -48,11 +46,11 @@ public class ToolRunProfile implements ModuleRunProfile{ public ToolRunProfile(final Tool tool, final DataContext context) { myTool = tool; myCommandLine = myTool.createCommandLine(context); - if (context instanceof DataManagerImpl.MyDataContext) { - // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext - // since we know exactly that context is valid, we need to update its event count - ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount()); - } + //if (context instanceof DataManagerImpl.MyDataContext) { + // // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext + // // since we know exactly that context is valid, we need to update its event count + // ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount()); + //} } public String getName() { diff --git a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java index 12da4eca007a..772ef0aafbf9 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/DataManagerImpl.java @@ -308,7 +308,7 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent PlatformDataKeys.MODALITY_STATE.getName() )); - public class MyDataContext implements DataContext, UserDataHolder { + public static class MyDataContext implements DataContext, UserDataHolder { private int myEventCount; // To prevent memory leak we have to wrap passed component into // the weak reference. For example, Swing often remembers menu items @@ -322,7 +322,9 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent myRef = new WeakReference(component); } - public void setEventCount(int eventCount) { + + public void setEventCount(int eventCount, Object caller) { + assert caller instanceof IdeKeyEventDispatcher : "This method might be accessible from " + IdeKeyEventDispatcher.class.getName() + " only"; myCachedData.clear(); myEventCount = eventCount; } @@ -366,11 +368,11 @@ public class DataManagerImpl extends DataManager implements ApplicationComponent return _component != null ? ModalityState.stateForComponent(_component) : ModalityState.NON_MODAL; } else if (PlatformDataKeys.EDITOR.is(dataId)) { - Editor editor = (Editor)DataManagerImpl.this.getData(dataId, _component); + Editor editor = (Editor)(((DataManagerImpl)DataManager.getInstance()).getData(dataId, _component)); return validateEditor(editor); } else { - return DataManagerImpl.this.getData(dataId, _component); + return (((DataManagerImpl)DataManager.getInstance()).getData(dataId, _component)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index 68e57274cc2f..7c1189ed1da4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -580,7 +580,7 @@ public final class IdeKeyEventDispatcher implements Disposable { processor.onUpdatePassed(e, action, actionEvent); - ((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount()); + ((DataManagerImpl.MyDataContext)myContext.getDataContext()).setEventCount(IdeEventQueue.getInstance().getEventCount(), this); actionManager.fireBeforeActionPerformed(action, actionEvent.getDataContext(), actionEvent); Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(actionEvent.getDataContext()); if (component != null && !component.isShowing()) { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetActionStub.java b/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetActionStub.java index 2b87fe26096a..c6496d4d74d8 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetActionStub.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetActionStub.java @@ -16,8 +16,6 @@ package com.intellij.lang.ant.config.actions; -import com.intellij.ide.IdeEventQueue; -import com.intellij.ide.impl.DataManagerImpl; import com.intellij.lang.ant.config.AntBuildFile; import com.intellij.lang.ant.config.AntConfiguration; import com.intellij.lang.ant.config.AntConfigurationListener; @@ -25,7 +23,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -83,12 +80,12 @@ public class TargetActionStub extends AnAction implements Disposable { return; } if (!myActionInvoked.getAndSet(true)) { - final DataContext context = e.getDataContext(); - if (context instanceof DataManagerImpl.MyDataContext) { - // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext - // since we know exactly that context is valid, we need to update its event count - ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount()); - } + //final DataContext context = e.getDataContext(); + //if (context instanceof DataManagerImpl.MyDataContext) { + // // hack: macro.expand() can cause UI events such as showing dialogs ('Prompt' macro) which may 'invalidate' the datacontext + // // since we know exactly that context is valid, we need to update its event count + // ((DataManagerImpl.MyDataContext)context).setEventCount(IdeEventQueue.getInstance().getEventCount()); + //} action.actionPerformed(e); } } From bcc709fe57d338378e314c135825f8dd499d6a33 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 18 May 2012 13:17:27 +0400 Subject: [PATCH 5/6] npe --- .../plugins/groovy/findUsages/LiteralConstructorReference.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java index 3cce2e414f6e..364620fcec53 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java @@ -144,7 +144,7 @@ public class LiteralConstructorReference extends PsiReferenceBase.Poly Date: Fri, 18 May 2012 14:34:56 +0400 Subject: [PATCH 6/6] IDEA-63669 Groovy: [ .. ].property is the same as [ .. ]*.property --- .../findUsages/GDKSuperMethodSearcher.java | 3 +- .../lang/psi/api/GroovyResolveResult.java | 13 +- .../groovy/lang/psi/api/SpreadState.java | 55 +++++ .../groovy/lang/psi/impl/GrSpreadType.java | 78 +++++++ .../psi/impl/GroovyResolveResultImpl.java | 36 ++-- .../GrConstructorInvocationImpl.java | 2 +- .../CompleteReferenceExpression.java | 12 +- .../GrReferenceExpressionImpl.java | 191 ++++++++++-------- .../expressions/GrReferenceResolveUtil.java | 106 +++++----- .../statements/expressions/TypesUtil.java | 51 ++++- .../DefaultCallExpressionTypeCalculator.java | 65 +++--- .../expressions/path/GrDGMTypeCalculator.java | 49 +---- .../expressions/path/GrIndexPropertyImpl.java | 2 +- .../enumConstant/GrEnumConstantImpl.java | 4 +- .../types/GrCodeReferenceElementImpl.java | 2 +- .../groovy/lang/psi/util/GdkMethodUtil.java | 12 +- .../plugins/groovy/lang/psi/util/PsiUtil.java | 2 +- .../groovy/lang/resolve/ResolveUtil.java | 54 ++--- .../processors/AccessorResolverProcessor.java | 4 +- .../processors/MethodResolverProcessor.java | 7 +- .../resolve/processors/ResolverProcessor.java | 4 +- .../lang/resolve/ResolveMethodTest.groovy | 2 +- .../lang/resolve/TypeInferenceTest.groovy | 51 +++++ 23 files changed, 518 insertions(+), 287 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/SpreadState.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java index 3e604a744937..3f4182719b1d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GDKSuperMethodSearcher.java @@ -61,7 +61,8 @@ public class GDKSuperMethodSearcher implements QueryExecutor SPREAD_STATE = Key.create("Spread state"); + + private final PsiType containerType; + @Nullable private final SpreadState innerState; + + public SpreadState(PsiType type, @Nullable SpreadState state) { + containerType = type; + innerState = state; + } + + public PsiType getContainerType() { + return containerType; + } + + @Nullable + public SpreadState getInnerState() { + return innerState; + } + + public static SpreadState create(PsiType type, @Nullable SpreadState state) { + return new SpreadState(type, state); + } + + public static PsiType apply(PsiType item, @Nullable SpreadState state, Project project) { + if (state == null) return item; + return apply(TypesUtil.createSimilarCollection(state.getContainerType(), project, item), state.getInnerState(), project); + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java new file mode 100644 index 000000000000..99b1556901de --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrSpreadType.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy.lang.psi.impl; + +import com.intellij.openapi.project.Project; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiType; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; + +/** + * @author Max Medvedev + */ +public class GrSpreadType extends GrLiteralClassType { + + private PsiType myType; + + public GrSpreadType(PsiType original, PsiType containerType, GlobalSearchScope scope) { + this(original, containerType, LanguageLevel.JDK_1_5, scope, JavaPsiFacade.getInstance(scope.getProject())); + } + + public GrSpreadType(PsiType original, PsiType containerType, LanguageLevel languageLevel, GlobalSearchScope scope, JavaPsiFacade facade) { + super(languageLevel, scope, facade); + + final Project project = facade.getProject(); + myType = TypesUtil.createSimilarCollection(containerType, project, original); + } + + @NotNull + @Override + protected String getJavaClassName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + public String getClassName() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + public PsiType[] getParameters() { + return new PsiType[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @NotNull + @Override + public PsiClassType setLanguageLevel(@NotNull LanguageLevel languageLevel) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public String getInternalCanonicalText() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isValid() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java index e8b06b9c8eee..0f4521128023 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java @@ -16,10 +16,12 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GrClassSubstitutor; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState; /** * @author ven @@ -31,28 +33,30 @@ public class GroovyResolveResultImpl implements GroovyResolveResult { private final PsiSubstitutor mySubstitutor; private final boolean myIsInvokedOnProperty; - private GroovyPsiElement myCurrentFileResolveContext; + private final GroovyPsiElement myCurrentFileResolveContext; + private final SpreadState mySpreadState; - public GroovyResolveResultImpl(PsiElement element, boolean isAccessible) { - this(element, null, PsiSubstitutor.EMPTY, isAccessible, true); + public GroovyResolveResultImpl(@NotNull PsiElement element, boolean isAccessible) { + this(element, null, null, PsiSubstitutor.EMPTY, isAccessible, true, false); } - public GroovyResolveResultImpl(PsiElement element, - @Nullable GroovyPsiElement context, - PsiSubstitutor substitutor, + public GroovyResolveResultImpl(@NotNull PsiElement element, + @Nullable GroovyPsiElement resolveContext, + @Nullable SpreadState spreadState, + @NotNull PsiSubstitutor substitutor, boolean isAccessible, boolean staticsOK) { - this(element, context, substitutor, isAccessible, staticsOK, false); + this(element, resolveContext, spreadState, substitutor, isAccessible, staticsOK, false); } public GroovyResolveResultImpl(PsiClassType.ClassResolveResult classResolveResult) { - this(classResolveResult.getElement(), null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(), - classResolveResult.isStaticsScopeCorrect()); + this(classResolveResult.getElement(), null, null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(), classResolveResult.isStaticsScopeCorrect(), false); } - public GroovyResolveResultImpl(PsiElement element, - GroovyPsiElement resolveContext, - PsiSubstitutor substitutor, + public GroovyResolveResultImpl(@NotNull PsiElement element, + @Nullable GroovyPsiElement resolveContext, + @Nullable SpreadState spreadState, + @NotNull PsiSubstitutor substitutor, boolean isAccessible, boolean staticsOK, boolean isInvokedOnProperty) { @@ -62,8 +66,10 @@ public class GroovyResolveResultImpl implements GroovyResolveResult { mySubstitutor = substitutor; myIsStaticsOK = staticsOK; myIsInvokedOnProperty = isInvokedOnProperty; + mySpreadState = spreadState; } + @NotNull public PsiSubstitutor getSubstitutor() { return mySubstitutor; } @@ -108,6 +114,7 @@ public class GroovyResolveResultImpl implements GroovyResolveResult { return result; } + @Nullable public GroovyPsiElement getCurrentFileResolveContext() { return myCurrentFileResolveContext; } @@ -116,6 +123,11 @@ public class GroovyResolveResultImpl implements GroovyResolveResult { return myIsInvokedOnProperty; } + @Override + public SpreadState getSpreadState() { + return mySpreadState; + } + @Override public String toString() { return "GroovyResolveResultImpl{" + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java index b1eb3ea33932..e6c630bef390 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java @@ -95,7 +95,7 @@ public class GrConstructorInvocationImpl extends GrCallImpl implements GrConstru } public GroovyResolveResult[] multiResolveClass() { - return new GroovyResolveResult[]{new GroovyResolveResultImpl(getDelegatedClass(), this, PsiSubstitutor.EMPTY, true, true)}; + return new GroovyResolveResult[]{new GroovyResolveResultImpl(getDelegatedClass(), this, null, PsiSubstitutor.EMPTY, true, true)}; } public PsiMethod resolveMethod() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java index 080bc3d9e4cc..75e809c5b795 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java @@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; @@ -117,7 +118,7 @@ public class CompleteReferenceExpression { getVariantsFromQualifierForSpreadOperator(refExpr, processor, qualifier); } } - ResolveUtil.processCategoryMembers(refExpr, processor); + ResolveUtil.processCategoryMembers(refExpr, processor, ResolveState.initial()); } private static void getVariantsFromQualifierForSpreadOperator(GrReferenceExpression refExpr, @@ -206,8 +207,8 @@ public class CompleteReferenceExpression { final GrPropertyForCompletion field = new GrPropertyForCompletion(method, name, type); if (resolveResult != null) { - return new GroovyResolveResultImpl(field, resolveResult.getCurrentFileResolveContext(), resolveResult.getSubstitutor(), - resolveResult.isAccessible(), resolveResult.isStaticsOK()); + return new GroovyResolveResultImpl(field, resolveResult.getCurrentFileResolveContext(), resolveResult.getSpreadState(), + resolveResult.getSubstitutor(), resolveResult.isAccessible(), resolveResult.isStaticsOK(), false); } else { return new GroovyResolveResultImpl(field, true); @@ -377,12 +378,13 @@ public class CompleteReferenceExpression { boolean isAccessible = isAccessible(namedElement); final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT); + final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE); boolean isStaticsOK = isStaticsOK(namedElement, resolveContext, myParameters.getInvocationCount() <= 1); PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY); if (substitutor == null) substitutor = PsiSubstitutor.EMPTY; - consume(new GroovyResolveResultImpl(namedElement, resolveContext, substitutor, isAccessible, isStaticsOK)); + consume(new GroovyResolveResultImpl(namedElement, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK)); return true; } @@ -407,7 +409,7 @@ public class CompleteReferenceExpression { element = ((GrReflectedMethod)element).getBaseMethod(); if (!myProcessedMethodWithOptionalParams.add((GrMethod)element)) return; - result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(), + result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(), result.getSpreadState(), result.getSubstitutor(), result.isAccessible(), result.isStaticsOK(), result.isInvokedOnProperty()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index 8cdc0970c303..6c54eeebb8d3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -42,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; @@ -64,7 +65,8 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; -import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; +import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mAT; +import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mMEMBER_POINTER; /** * @author ilyas @@ -121,7 +123,8 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl accessorResults = new ArrayList(); for (String accessorName : accessorNames) { - AccessorResolverProcessor accessorResolver = new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments()); + AccessorResolverProcessor accessorResolver = + new AccessorResolverProcessor(accessorName, name, this, !isLValue, false, getThisType(), getTypeArguments()); GrReferenceResolveUtil.resolveImpl(accessorResolver, this); final GroovyResolveResult[] candidates = accessorResolver.getCandidates(); @@ -198,7 +202,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl>() { - @Override - public Result> compute() { - return Result.create(doResolveByShape(false, null), PsiModificationTracker.MODIFICATION_COUNT); - } - }); + return CachedValuesManager.getManager(getProject()) + .getCachedValue(this, new CachedValueProvider>() { + @Override + public Result> compute() { + return Result.create(doResolveByShape(false, null), PsiModificationTracker.MODIFICATION_COUNT); + } + }); } private Pair doResolveByShape(boolean allVariants, @Nullable GrExpression upToArgument) { @@ -329,7 +334,10 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl() { @Override public Result compute() { - GroovyResolveResult[] value = RecursionManager.doPreventingRecursion(GrReferenceExpressionImpl.this, true, new Computable() { - @Override - public GroovyResolveResult[] compute() { - return doPolyResolve(false, false); - } - }); + GroovyResolveResult[] value = + RecursionManager.doPreventingRecursion(GrReferenceExpressionImpl.this, true, new Computable() { + @Override + public GroovyResolveResult[] compute() { + return doPolyResolve(false, false); + } + }); if (value == null) { value = GroovyResolveResult.EMPTY_ARRAY; } @@ -459,8 +468,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl 1) { PsiParameter last = parameters[parameters.length - 1]; - return TypesUtil.substituteBoxAndNormalizeType(last.getType(), candidate.getSubstitutor(), this); + return TypesUtil.substituteBoxAndNormalizeType(last.getType(), candidate.getSubstitutor(), candidate.getSpreadState(), this); } } return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantImpl.java index be8c8d08977b..afd5148ac5c0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/enumConstant/GrEnumConstantImpl.java @@ -102,8 +102,7 @@ public class GrEnumConstantImpl extends GrFieldImpl implements GrEnumConstant { } public GroovyResolveResult[] multiResolveClass() { - final PsiClass psiClass = getContainingClass(); - GroovyResolveResult result = new GroovyResolveResultImpl(psiClass, this, PsiSubstitutor.EMPTY, true, true); + GroovyResolveResult result = new GroovyResolveResultImpl(getContainingClass(), this, null, PsiSubstitutor.EMPTY, true, true); return new GroovyResolveResult[]{result}; } @@ -135,7 +134,6 @@ public class GrEnumConstantImpl extends GrFieldImpl implements GrEnumConstant { public GrExpression[] getExpressionArguments() { final GrArgumentList argumentList = getArgumentList(); return argumentList == null ? GrExpression.EMPTY_ARRAY : argumentList.getExpressionArguments(); - } @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java index 239e24f42bc7..0aed67b8c24e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrCodeReferenceElementImpl.java @@ -376,7 +376,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImplp ''', "$JAVA_UTIL_MAP<$JAVA_LANG_STRING,$JAVA_LANG_STRING>") } + void testSpread1() { + myFixture.addClass('''\ +class A { + String getString() {return "a";} +}''') + doTest('''\ +[new A()].string +''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_STRING>") + } + + void testSpread2() { + + myFixture.addClass('''\ +class A { + String getString() {return "a";} +}''') + doTest('''\ +class Cat { + static getFoo(String b) {2} +} +use(Cat) { + [new A()].string.foo +} +''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_INTEGER>") + } + + void testSpread3() { + myFixture.addClass('''\ +class A { + String getString() {return "a";} +}''') + doTest('''\ +[[new A()]].string +''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_STRING>>") + } + + void testSpread4() { + myFixture.addClass('''\ +class A { + String getString() {return "a";} +}''') + doTest('''\ +class Cat { + static getFoo(String b) {2} +} + +use(Cat){ + [[new A()]].string.foo +} +''', "$JAVA_UTIL_ARRAY_LIST<$JAVA_UTIL_ARRAY_LIST<$JAVA_LANG_INTEGER>>") + } private void doTest(String text, String type) { def file = myFixture.configureByText('_.groovy', text)