Merge commit 'origin/master'
authorMaxim Medvedev <maxim.medvedev@jetbrains.com>
Sat, 27 Nov 2010 18:50:41 +0000 (21:50 +0300)
committerMaxim Medvedev <maxim.medvedev@jetbrains.com>
Sat, 27 Nov 2010 18:50:41 +0000 (21:50 +0300)
23 files changed:
java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java
java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterDialog.java
platform/lang-impl/src/com/intellij/codeInsight/editorActions/enter/EnterBetweenBracesHandler.java
platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
plugins/groovy/resources/standardDsls/defaultCollectionMethods.gdsl [new file with mode: 0644]
plugins/groovy/resources/standardDsls/enumMethods.gdsl
plugins/groovy/src/META-INF/plugin.xml
plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/editor/actions/GroovyEnterHandler.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClosureType.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java
plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java
plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java
plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java
plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
plugins/groovy/testdata/mockGroovyLib1.8/groovy-1.8.0-beta-2.jar [new file with mode: 0644]
plugins/groovy/testdata/refactoring/changeSignature/AddReturnType_after.groovy
plugins/groovy/testdata/resolve/inference/typeOfGroupBy/A.groovy [new file with mode: 0644]

index a5f1cd74ef4aabf8ee794935d98d736a0a3a3279..794f1eb251896c95286b9827d3498e0dc5b7469f 100644 (file)
@@ -381,6 +381,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr
         final PsiExpression[] args = list.getExpressions();
         final int nonVarargCount = getNonVarargCount(changeInfo, args);
         final int varargCount = args.length - nonVarargCount;
+        if (varargCount<0) return;
         PsiExpression[] newVarargInitializers = null;
 
         final int newArgsLength;
index 5bb05430be78d231d041a95ad596f4f3e0e379de..f4c21565fed9c6e2e13dd84195ae86a7f4b4090d 100644 (file)
@@ -156,7 +156,7 @@ public class IntroduceParameterDialog extends RefactoringDialog {
   }
 
   private String getParameterName() {
-    return  myParameterNameField.getEnteredName();
+    return  myParameterNameField.getEnteredName().trim();
   }
 
   private int getReplaceFieldsWithGetters() {
@@ -461,7 +461,7 @@ public class IntroduceParameterDialog extends RefactoringDialog {
   @Override
   protected void canRun() throws ConfigurationException {
     String name = getParameterName();
-    if (name == null || !JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(name.trim())) {
+    if (name == null || !JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(name)) {
       throw new ConfigurationException("\'" + StringUtil.first(name != null ? name : "", 10 , true) + "\' is invalid parameter name");
     }
   }
index d81a4bb39a803d962a8f25ed9983a7efc60a9cc3..6070fdf221d8af82920c1bbbf1db72f34bb3e7c0 100644 (file)
@@ -16,6 +16,9 @@
 
 package com.intellij.codeInsight.editorActions.enter;
 
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.lang.ParserDefinition;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
@@ -23,6 +26,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Ref;
 import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.codeStyle.CodeStyleManager;
 import com.intellij.util.IncorrectOperationException;
index 4ff8945d99204975587f6acb7d3e698786040e8f..debe45381d6e8553f83ea54312622b8594dd0e29 100644 (file)
@@ -17,10 +17,7 @@ package com.intellij.openapi.editor.actions;
 
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.ScrollType;
-import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
 import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -44,9 +41,11 @@ public class SplitLineAction extends EditorAction {
     }
 
     public void executeWriteAction(Editor editor, DataContext dataContext) {
-      LogicalPosition caretPosition = editor.getCaretModel().getLogicalPosition();
-
       final Document document = editor.getDocument();
+      final RangeMarker rangeMarker =
+        document.createRangeMarker(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset() );
+      rangeMarker.setGreedyToLeft(false);
+      rangeMarker.setGreedyToRight(false);
       final CharSequence chars = document.getCharsSequence();
 
       int offset = editor.getCaretModel().getOffset();
@@ -65,7 +64,7 @@ public class SplitLineAction extends EditorAction {
       } else {
         getEnterHandler().execute(editor, dataContext);
 
-        editor.getCaretModel().moveToLogicalPosition(caretPosition);
+        editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset());
         editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
       }
 
diff --git a/plugins/groovy/resources/standardDsls/defaultCollectionMethods.gdsl b/plugins/groovy/resources/standardDsls/defaultCollectionMethods.gdsl
new file mode 100644 (file)
index 0000000..3bc2641
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2010 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 standardDsls
+/**
+ * @author Maxim.Medvedev
+ */
+
+def extractTypeParameter(def typeText) {
+  final int start = typeText.indexOf('<')
+  final int end = typeText.lastIndexOf('>')
+
+  if (start < 0) return null
+  if (end < 0) return typeText.substring(start + 1)
+  return typeText.substring(start + 1, end);
+}
+
+def constructTypeArg(def psiType) {
+  def typeText = psiType.canonicalText ?: psiType.presentableText
+  if (!typeText) return ""
+  def arg = extractTypeParameter(typeText)
+  if (!arg) return ""
+  return "<$arg>"
+}
+
+contributor(ctype: "java.util.Collection") {
+  method name: "getAt", params: [arg: "java.lang.Number"], type: extractTypeParameter(psiType.canonicalText ?: psiType.presentableText)
+  method name: "getAt", params: [arg: "groovy.lang.Range"], type: "java.util.List${constructTypeArg(psiType)}"
+  method name: "getAt", params: [arg: "java.util.Collection"], type: "java.util.List${constructTypeArg(psiType)}"
+}
\ No newline at end of file
index ccd10ad43be65318fc795bb1e4b774f24e9cd625..19e18f48194f314c13c62a12f40b78ca5de6de4e 100644 (file)
@@ -19,7 +19,7 @@ package standardDsls
  */
 
 contributor (ctype:'java.lang.Enum') {
-  method name:'values', type:'java.util.Collection', isStatic:true
+  method name: 'values', type: "java.util.Collection<${psiType.canonicalText ?: psiType.presentableText}>", isStatic: true
   method name: 'valueOf', type: psiType.canonicalText, params: [name: 'java.lang.String'], isStatic:true
   method name: 'next', type: psiType.canonicalText
   method name: 'previous', type: psiType.canonicalText
index f8cc98db1b3df5085fcd3edbcfebea35e17d6211..5e4ba3cdeb9cf63f586de721669f3fd17b5bbb02 100644 (file)
     <lang.foldingBuilder language="Groovy" implementationClass="org.jetbrains.plugins.groovy.lang.folding.GroovyFoldingBuilder"/>
     <lang.formatter language="Groovy" implementationClass="org.jetbrains.plugins.groovy.formatter.GroovyFormattingModelBuilder"/>
 
-    <enterHandlerDelegate implementation="org.jetbrains.plugins.groovy.lang.editor.actions.GroovyEnterHandler" order="after EnterBetweenBracesHandler"/>
+    <enterHandlerDelegate implementation="org.jetbrains.plugins.groovy.lang.editor.actions.GroovyEnterHandler"
+                          order="before EnterBetweenBracesHandler"/>
     <typedHandler implementation="org.jetbrains.plugins.groovy.lang.editor.actions.GStringTypedActionHandler"/>
     <backspaceHandlerDelegate implementation="org.jetbrains.plugins.groovy.lang.editor.actions.GStringBackspaceHandlerDelegate"/>
 
index aaced50fb93db6054d1e5e8d1dc59cfbef9f5ed3..fdaf1e5835e8a9c4cb0abb9cf0db89b7528208ca 100644 (file)
@@ -30,12 +30,10 @@ import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightElement;
 import com.intellij.psi.infos.CandidateInfo;
 import com.intellij.psi.search.searches.SuperMethodsSearch;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.MethodSignature;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.*;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.intellij.util.containers.HashSet;
@@ -243,7 +241,7 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
     }
   }
 
-  private static void registerAccessFix(Annotation annotation, GrReferenceExpression place, PsiMember refElement) {
+  private static void registerAccessFix(Annotation annotation, PsiElement place, PsiMember refElement) {
     if (refElement instanceof PsiCompiledElement) return;
     PsiModifierList modifierList = refElement.getModifierList();
     if (modifierList == null) return;
@@ -419,6 +417,9 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
         if (parent instanceof GrClosableBlock) {
           duplicate = ResolveUtil
             .resolveExistingElement((GrClosableBlock)parent, new DuplicateVariablesProcessor(variable), GrVariable.class, GrReferenceExpression.class);
+          if (duplicate instanceof LightElement) {
+            duplicate = null;
+          }
         }
       }
     }
@@ -566,6 +567,19 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
           ((PsiMethod)constructor).getParameterList().getParametersCount() == 0) {
         checkDefaultMapConstructor(myHolder, argList, constructor);
       }
+
+      if (!constructorResolveResult.isAccessible()) {
+        String message = GroovyBundle.message("cannot.access", PsiFormatUtil.formatMethod((PsiMethod)constructor, PsiSubstitutor.EMPTY,
+                                                                                          PsiFormatUtil.SHOW_NAME |
+                                                                                          PsiFormatUtil.SHOW_TYPE |
+                                                                                          PsiFormatUtil.TYPE_AFTER |
+                                                                                          PsiFormatUtil.SHOW_PARAMETERS,
+                                                                                          PsiFormatUtil.SHOW_TYPE
+        ));
+        final Annotation annotation = myHolder.createWarningAnnotation(getElementToHighlight(refElement), message);
+        registerAccessFix(annotation, refElement, ((PsiMember)constructor));
+      }
+
     }
     else {
       final GroovyResolveResult[] results = newExpression.multiResolveConstructor();
index d37cc837b01f30132b8bace52d2c68863a27e1f2..e0ace5309af5c4241b9cbe60801bce46f6fbd9ef 100644 (file)
@@ -86,10 +86,16 @@ public class GroovyInsertHandler implements InsertHandler<LookupElement> {
 
       if (PsiTreeUtil.getParentOfType(elementAt, GrImportStatement.class) != null) return;
 
-      if (parameters.length == 1 && CLOSURE_CLASS.equals(parameters[0].getType().getCanonicalText())) {
-        document.insertString(offset, " {}");
-        caretModel.moveToOffset(offset + 2);
-        return;
+      if (parameters.length == 1) {
+        final PsiType type = parameters[0].getType();
+        if (type instanceof PsiClassType) {
+          final PsiClass psiClass = ((PsiClassType)type).resolve();
+          if (psiClass != null && CLOSURE_CLASS.equals(psiClass.getQualifiedName())) {
+            document.insertString(offset, " {}");
+            caretModel.moveToOffset(offset + 2);
+            return;
+          }
+        }
       }
 
       PsiDocumentManager docManager = PsiDocumentManager.getInstance(method.getProject());
@@ -97,7 +103,8 @@ public class GroovyInsertHandler implements InsertHandler<LookupElement> {
       PsiFile psiFile = docManager.getPsiFile(document);
       if (method instanceof GrMethod &&
           method.getParameterList().getParametersCount() > 0 &&
-          method.getContainingClass() instanceof GroovyScriptClass) {
+          method.getContainingClass() instanceof GroovyScriptClass &&
+          isExpressionStatement(psiFile, context.getStartOffset())) {
         return;
       }
       if (isExpressionStatement(psiFile, context.getStartOffset()) &&
index 8af04c2e6a70b52c02a56776878de3e145815983..4594c308a3f144b2ce9ca670abacee2c23385edd 100644 (file)
@@ -87,7 +87,7 @@ public class GroovyEnterHandler implements EnterHandlerDelegate {
         if (element != null &&
             element.getNode().getElementType() == mRCURLY &&
             element.getParent() instanceof GrClosableBlock &&
-            text.length() > caret) {
+            text.length() > caret && afterArrow) {
           return Result.DefaultForceIndent;
         }
       }
@@ -187,7 +187,8 @@ public class GroovyEnterHandler implements EnterHandlerDelegate {
         String text = node.getText();
         String innerText = text.equals("''") ? "" : text.substring(1, text.length() - 1);
         TextRange literalRange = stringElement.getTextRange();
-        document.replaceString(literalRange.getStartOffset(), literalRange.getEndOffset(), "'''" + innerText + "'''");
+        document.insertString(literalRange.getEndOffset(), "''");
+        document.insertString(literalRange.getStartOffset(), "''");
         editor.getCaretModel().moveToOffset(caretOffset + 2);
         EditorModificationUtil.insertStringAtCaret(editor, "\n");
       }
@@ -223,7 +224,8 @@ public class GroovyEnterHandler implements EnterHandlerDelegate {
         String text = parent.getText();
         String innerText = text.equals("\"\"") ? "" : text.substring(1, text.length() - 1);
         TextRange parentRange = parent.getTextRange();
-        document.replaceString(parentRange.getStartOffset(), parentRange.getEndOffset(), "\"\"\"" + innerText + "\"\"\"");
+        document.insertString(parentRange.getEndOffset(), "\"\"");
+        document.insertString(parentRange.getStartOffset(), "\"\"");
         editor.getCaretModel().moveToOffset(caretOffset + 2);
         EditorModificationUtil.insertStringAtCaret(editor, "\n");
         if (rightFromDollar) {
index 72b4380ecca5078db2c45a487cb35560bbdfd30b..efe551f41c7aa4400fb174898c8f5c0c031d6801 100644 (file)
@@ -19,7 +19,9 @@ package org.jetbrains.plugins.groovy.lang.psi.impl;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.pom.java.LanguageLevel;
 import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiSubstitutorImpl;
 import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.HashMap;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -28,6 +30,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
 import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
 
+import java.util.Map;
+
 /**
  * @author ven
  */
@@ -35,12 +39,20 @@ public class GrClosureType extends PsiClassType {
   private final GlobalSearchScope myScope;
   private final PsiManager myManager;
   private final @NotNull GrClosureSignature mySignature;
+  private final PsiType[] myTypeArgs;
 
   private GrClosureType(LanguageLevel languageLevel, GlobalSearchScope scope, PsiManager manager, @NotNull GrClosureSignature closureSignature) {
     super(languageLevel);
     myScope = scope;
     myManager = manager;
     mySignature = closureSignature;
+    final PsiClass psiClass = resolve();
+    if (psiClass!=null && psiClass.getTypeParameters().length==1) {
+      myTypeArgs = new PsiType[]{mySignature.getReturnType()};
+    }
+    else {
+      myTypeArgs = PsiType.EMPTY_ARRAY;
+    }
   }
 
   @Nullable
@@ -54,19 +66,30 @@ public class GrClosureType extends PsiClassType {
 
   @NotNull
   public PsiType[] getParameters() {
-    //todo
-    return PsiType.EMPTY_ARRAY;
+    return myTypeArgs;
   }
 
   @NotNull
   public ClassResolveResult resolveGenerics() {
+    final PsiClass closure = resolve();
+    final PsiSubstitutor substitutor;
+    if (closure != null && closure.getTypeParameters().length == 1) {
+      final PsiTypeParameter parameter = closure.getTypeParameters()[0];
+      final Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
+      map.put(parameter, mySignature.getReturnType());
+      substitutor = PsiSubstitutorImpl.createSubstitutor(map);
+    }
+    else {
+      substitutor = PsiSubstitutor.EMPTY;
+    }
+
     return new ClassResolveResult() {
       public PsiClass getElement() {
-        return resolve();
+        return closure;
       }
 
       public PsiSubstitutor getSubstitutor() {
-        return PsiSubstitutor.UNKNOWN;
+        return substitutor;
       }
 
       public boolean isPackagePrefixPackageReference() {
@@ -99,12 +122,22 @@ public class GrClosureType extends PsiClassType {
 
   @NotNull
   public String getPresentableText() {
-    return "Closure";
+    if (myTypeArgs.length == 0 || myTypeArgs[0] == null) {
+      return "Closure";
+    }
+    else {
+      return "Closure<" + myTypeArgs[0].getPresentableText() + ">";
+    }
   }
 
   @Nullable
   public String getCanonicalText() {
-    return GrClosableBlock.GROOVY_LANG_CLOSURE;
+    if (myTypeArgs.length == 0 || myTypeArgs[0] == null) {
+      return GrClosableBlock.GROOVY_LANG_CLOSURE;
+    }
+    else {
+      return GrClosableBlock.GROOVY_LANG_CLOSURE + "<" + myTypeArgs[0].getCanonicalText() + ">";
+    }
   }
 
   @Nullable
index 2d92fec1267d20a50f88d08d449bb204a0b7f676..87ca2e584d95d37ee9d67fdcda67c30262929406 100644 (file)
@@ -58,12 +58,14 @@ public class GrMapType extends GrLiteralClassType {
   public GrMapType(JavaPsiFacade facade,
                    GlobalSearchScope scope,
                    Map<String, PsiType> stringEntries,
-                   List<Pair<PsiType, PsiType>> otherEntries, LanguageLevel languageLevel) {
+                   List<Pair<PsiType, PsiType>> otherEntries,
+                   LanguageLevel languageLevel) {
     super(languageLevel, scope, facade);
     myStringEntries = stringEntries;
     myOtherEntries = otherEntries;
 
-    myJavaClassName = facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : CommonClassNames.JAVA_UTIL_MAP;
+    myJavaClassName =
+      facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : CommonClassNames.JAVA_UTIL_MAP;
   }
 
   @Override
@@ -72,7 +74,7 @@ public class GrMapType extends GrLiteralClassType {
   }
 
   public String getClassName() {
-    return "Map";
+    return StringUtil.getShortName(myJavaClassName);
   }
 
   public PsiType[] getAllKeyTypes() {
index 7ef644df7851eba2a1affcdba04a447f2cc4ba5c..a553310d51273297b0966949623f86bb742fe56b 100644 (file)
@@ -54,6 +54,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe
 import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.GrTopStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
 import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
 import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFileStub;
 import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -102,8 +103,8 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile {
 
   private GrParameter getSyntheticArgsParameter() {
     if (mySyntheticArgsParameter == null) {
-      final GrParameter candidate =
-        GroovyPsiElementFactory.getInstance(getProject()).createParameter(SYNTHETIC_PARAMETER_NAME, "java.lang.String[]", this);
+      final PsiType psiType = JavaPsiFacade.getElementFactory(getProject()).createTypeFromText("java.lang.String[]", this);
+      final GrParameter candidate = new GrLightParameter(SYNTHETIC_PARAMETER_NAME, psiType, this);
       synchronized (lock) {
         if (mySyntheticArgsParameter == null) {
           mySyntheticArgsParameter = candidate;
index caeb353036bf5439c91c6eeed81389f8dd79c5c4..2fdb7aac0a1e734e379d7217e8390396d3346c2c 100644 (file)
@@ -388,7 +388,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
       assert defintion != null && defintion instanceof GrMethod;
       return ((GrMethod)defintion);
     }
-    catch (Error error) {
+    catch (Exception error) {
       throw new IncorrectOperationException("Can't create method from text: '" + file.getText() + "'");
     }
   }
index 4603d529bacc93636b8e3b003919e119e2bb7a60..722d5388964bf9a2f118ae43fe0e24e6cc2c4b38 100644 (file)
@@ -520,7 +520,10 @@ public class ResolveUtil {
   }
 
   public static boolean isInUseScope(GroovyResolveResult resolveResult) {
-    final GroovyPsiElement context = resolveResult.getCurrentFileResolveContext();
+    return isInUseScope(resolveResult.getCurrentFileResolveContext());
+  }
+
+  public static boolean isInUseScope(GroovyPsiElement context) {
     if (context instanceof GrMethodCall) {
       final GrExpression expression = ((GrMethodCall)context).getInvokedExpression();
       if (expression instanceof GrReferenceExpression) {
@@ -532,4 +535,20 @@ public class ResolveUtil {
     }
     return false;
   }
+
+  public static boolean isInWithContext(GroovyPsiElement context) {
+    if (context instanceof GrExpression) {
+      final PsiElement parent = context.getParent();
+      if (parent instanceof GrReferenceExpression && ((GrReferenceExpression)parent).getQualifier() == context) {
+        final PsiElement pparent = parent.getParent();
+        if (pparent instanceof GrMethodCall) {
+          final PsiMethod method = ((GrMethodCall)pparent).resolveMethod();
+          if (method instanceof GrGdkMethod && "with".equals(method.getName())) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
 }
index 89dc524d85e9b72dfbcaad520c6cc02af77f5160..88d25bd301f20b7d259581f01bb2945238c74cdd 100644 (file)
@@ -31,7 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
@@ -83,14 +83,16 @@ public class MethodResolverProcessor extends ResolverProcessor {
 
       if (method.isConstructor() != myIsConstructor) return true;
       if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
-      substitutor = obtainSubstitutor(substitutor, method);
+      substitutor = obtainSubstitutor(substitutor, method, state);
       boolean isAccessible = isAccessible(method);
-      GroovyPsiElement fileResolveContext = state.get(RESOLVE_CONTEXT);
-      boolean isStaticsOK = isStaticsOK(method, fileResolveContext);
-      if (!myAllVariants && PsiUtil.isApplicable(myArgumentTypes, method, substitutor, fileResolveContext instanceof GrMethodCallExpression, (GroovyPsiElement)myPlace) && isStaticsOK) {
-        addCandidate(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
+      GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
+      boolean isStaticsOK = isStaticsOK(method, resolveContext);
+      if (!myAllVariants &&
+          PsiUtil.isApplicable(myArgumentTypes, method, substitutor, ResolveUtil.isInUseScope(resolveContext), (GroovyPsiElement)myPlace) &&
+          isStaticsOK) {
+        addCandidate(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK));
       } else {
-        myInapplicableCandidates.add(new GroovyResolveResultImpl(method, fileResolveContext, substitutor, isAccessible, isStaticsOK));
+        myInapplicableCandidates.add(new GroovyResolveResultImpl(method, resolveContext, substitutor, isAccessible, isStaticsOK));
       }
 
       return true;
@@ -99,7 +101,7 @@ public class MethodResolverProcessor extends ResolverProcessor {
     return true;
   }
 
-  private PsiSubstitutor obtainSubstitutor(PsiSubstitutor substitutor, PsiMethod method) {
+  private PsiSubstitutor obtainSubstitutor(PsiSubstitutor substitutor, PsiMethod method, ResolveState state) {
     final PsiTypeParameter[] typeParameters = method.getTypeParameters();
     if (myTypeArguments.length == typeParameters.length) {
       for (int i = 0; i < typeParameters.length; i++) {
@@ -116,7 +118,13 @@ public class MethodResolverProcessor extends ResolverProcessor {
         assert argTypes != null;
         //type inference should be performed from static method
         PsiType[] newArgTypes = new PsiType[argTypes.length + 1];
-        newArgTypes[0] = myThisType;
+        final GroovyPsiElement resolveContext = state.get(RESOLVE_CONTEXT);
+        if (ResolveUtil.isInWithContext(resolveContext)) {
+          newArgTypes[0] = ((GrExpression)resolveContext).getType();
+        }
+        else {
+          newArgTypes[0] = myThisType;
+        }
         System.arraycopy(argTypes, 0, newArgTypes, 1, argTypes.length);
         argTypes = newArgTypes;
 
index 99528fd696c596e2dd0d10888fa697662ef8901b..25417202d1140813b59d4bc4710f8fdb47beb488 100644 (file)
@@ -182,20 +182,20 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
       }
     }
 
+    final GrModifierList modifierList = method.getModifierList();
     if (changeInfo.isVisibilityChanged()) {
-      method.getModifierList().setModifierProperty(changeInfo.getNewVisibility(), true);
+      modifierList.setModifierProperty(changeInfo.getNewVisibility(), true);
     }
 
     PsiSubstitutor substitutor = baseMethod != null ? calculateSubstitutor(method, baseMethod) : PsiSubstitutor.EMPTY;
 
     final PsiMethod context = changeInfo.getMethod();
+    GrTypeElement oldReturnTypeElement = method.getReturnTypeElementGroovy();
     if (changeInfo.isReturnTypeChanged()) {
       CanonicalTypes.Type newReturnType = changeInfo.getNewReturnType();
-      GrTypeElement element = method.getReturnTypeElementGroovy();
       if (newReturnType == null) {
-        if (element != null) {
-          element.delete();
-          GrModifierList modifierList = method.getModifierList();
+        if (oldReturnTypeElement != null) {
+          oldReturnTypeElement.delete();
           if (modifierList.getModifiers().length == 0) {
             modifierList.setModifierProperty(GrModifier.DEF, true);
           }
@@ -205,8 +205,11 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc
         PsiType type = newReturnType.getType(context, method.getManager());
         final PsiType oldReturnType = method.getReturnType();
         if (!TypesUtil
-          .isAssignable(type, oldReturnType, context.getManager(), context.getResolveScope())) { //todo ask for replace covariant type
+          .isAssignableByMethodCallConversion(type, oldReturnType, context.getManager(), context.getResolveScope())) { //todo ask for replace covariant type
           method.setReturnType(substitutor.substitute(type));
+          if (oldReturnTypeElement==null) {
+            modifierList.setModifierProperty(GrModifier.DEF, false);;
+          }
         }
       }
     }
index ef0f5332af287bf69d281f1c1e6ec86e40485298..8b1a8ee8aa2963bf51e3cf978a4ff65789b8eeb4 100644 (file)
@@ -52,7 +52,7 @@ public abstract class LightGroovyTestCase extends LightCodeInsightFixtureTestCas
     public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
       final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel();
       final VirtualFile groovyJar =
-        JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_7LibraryName()+"!/");
+        JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_8LibraryName()+"!/");
       modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES);
       modifiableModel.commit();
     }
index 114a6b5dc10d559386cafec8a2f189b4c0fc4910..51513f30e03b8089f51f7cb1e29f2d7652165f4f 100644 (file)
@@ -15,9 +15,7 @@
  */
 package org.jetbrains.plugins.groovy.lang.resolve;
 
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiIntersectionType;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
 import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
 import org.jetbrains.plugins.groovy.util.TestUtils;
@@ -142,4 +140,16 @@ public class TypeInferenceTest extends GroovyResolveTestCase {
   public void testRawTypeInReturnExpression() {
     assertNotNull(resolve("A.groovy"));
   }
+
+  private void assertTypeEquals(String expected, String fileName) {
+    final PsiReference ref = configureByFile(getTestName(true) + "/" + fileName);
+    assertInstanceOf(ref, GrReferenceExpression.class);
+    final PsiType type = ((GrReferenceExpression)ref).getType();
+    assertNotNull(type);
+    assertEquals(expected, type.getCanonicalText());
+  }
+
+  public void testTypeOfGroupBy() {
+    assertTypeEquals("java.util.Map<java.lang.Integer,java.util.List<java.lang.Integer>>", "A.groovy");
+  }
 }
index 2012f5d59673328ed5438bbcf87368c87446536e..3e222f3fcbdd24de792fccdd213dfab7469a4be7 100644 (file)
@@ -44,6 +44,7 @@ public abstract class TestUtils {
   public static final String END_MARKER = "<end>";
   public static final String GROOVY_JAR = "groovy-all.jar";
   public static final String GROOVY_JAR_17 = "groovy-all-1.7.jar";
+  public static final String GROOVY_JAR_18 = "groovy-1.8.0-beta-2.jar";
 
   public static String getMockJdkHome() {
     return getAbsoluteTestDataPath() + "/mockJDK";
@@ -61,6 +62,14 @@ public abstract class TestUtils {
     return getMockGroovy1_7LibraryHome()+"/groovy-all-1.7.3.jar";
   }
 
+  public static String getMockGroovy1_8LibraryHome() {
+    return getAbsoluteTestDataPath() + "/mockGroovyLib1.8";
+  }
+
+  public static String getMockGroovy1_8LibraryName() {
+    return getMockGroovy1_8LibraryHome()+"/"+GROOVY_JAR_18;
+  }
+
   public static PsiFile createPseudoPhysicalGroovyFile(final Project project, final String text) throws IncorrectOperationException {
     return createPseudoPhysicalFile(project, TEMP_FILE, text);
   }
diff --git a/plugins/groovy/testdata/mockGroovyLib1.8/groovy-1.8.0-beta-2.jar b/plugins/groovy/testdata/mockGroovyLib1.8/groovy-1.8.0-beta-2.jar
new file mode 100644 (file)
index 0000000..dc45cc1
Binary files /dev/null and b/plugins/groovy/testdata/mockGroovyLib1.8/groovy-1.8.0-beta-2.jar differ
index f1e098a69e019e259b387ef5a6676bb5e293fffc..987b8ae651c629f35152baf5da50bb2f8a34efaa 100644 (file)
@@ -1,3 +1,3 @@
 class Foo {
-  def int foo(String s){}
+  int foo(String s){}
 }
\ No newline at end of file
diff --git a/plugins/groovy/testdata/resolve/inference/typeOfGroupBy/A.groovy b/plugins/groovy/testdata/resolve/inference/typeOfGroupBy/A.groovy
new file mode 100644 (file)
index 0000000..d2882c1
--- /dev/null
@@ -0,0 +1,4 @@
+[1, 2, 3].with {
+  def by = groupBy({2})
+  print b<ref>y
+}
\ No newline at end of file