IDEA-68175 multi-signature closure types

This commit is contained in:
Maxim.Medvedev
2012-05-06 13:42:47 +04:00
parent 459037f418
commit a29951851d
49 changed files with 797 additions and 401 deletions
@@ -103,9 +103,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.*;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
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.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
@@ -54,8 +54,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyConstantExpressionEvaluator;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
@@ -17,7 +17,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.AbstractClosureParameterEnhancer;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
@@ -15,7 +15,7 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesPr
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.ArrayList;
@@ -9,12 +9,12 @@ import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference;
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
/**
* @author peter
@@ -85,7 +85,7 @@ public class GppTypeConverter extends GrTypeConverter {
}
public static boolean isClosureOverride(PsiType[] methodParameters, GrClosureType closureType, GroovyPsiElement context) {
final GrClosureSignature signature = closureType.getSignature();
final GrSignature signature = closureType.getSignature();
if (methodParameters != null && GrClosureSignatureUtil.isSignatureApplicable(signature, methodParameters, context)) {
return true;
}
@@ -39,6 +39,7 @@ import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
@@ -47,9 +48,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.Collection;
@@ -123,8 +123,8 @@ public class ConvertClosureToMethodIntention extends Intention {
LOG.assertTrue(initializer != null);
final PsiType type = initializer.getType();
LOG.assertTrue(type instanceof GrClosureType);
final GrClosureSignature signature = ((GrClosureType)type).getSignature();
final List<MethodSignature> signatures = GrClosureSignatureUtil.generateAllMethodSignaturesByClosureSignature(fieldName, signature);
final GrSignature signature = ((GrClosureType)type).getSignature();
final List<MethodSignature> signatures = GrClosureSignatureUtil.generateAllMethodSignaturesBySignature(fieldName, signature);
for (MethodSignature s : signatures) {
final PsiMethod method = MethodSignatureUtil.findMethodBySignature(containingClass, s, true);
if (method != null) {
@@ -58,8 +58,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.List;
@@ -47,6 +47,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
@@ -60,10 +61,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.members.GrMethodImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.refactoring.GroovyValidationUtil;
@@ -20,13 +20,11 @@ import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.parameterInfo.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -35,6 +33,8 @@ import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrRecursiveSignatureVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -42,7 +42,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
@@ -131,32 +130,25 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
}
@SuppressWarnings("unchecked")
public void showParameterInfo(@NotNull GroovyPsiElement place, CreateParameterInfoContext context) {
public void showParameterInfo(@NotNull GroovyPsiElement place, @NotNull CreateParameterInfoContext context) {
GroovyResolveResult[] variants = ResolveUtil.getCallVariants(place);
final List elementToShow = new ArrayList();
final PsiElement parent = place.getParent();
if (parent instanceof GrMethodCall) {
final Condition<GroovyResolveResult> methodsOrClosures = new Condition<GroovyResolveResult>() {
public boolean value(GroovyResolveResult result) {
final PsiElement element = result.getElement();
return element instanceof PsiMethod && !result.isInvokedOnProperty() ||
element instanceof GrVariable && ((GrVariable)element).getTypeGroovy() instanceof GrClosureType;
}
};
final GrExpression invoked = ((GrMethodCall)parent).getInvokedExpression();
if (isPropertyOrVariableInvoked(invoked)) {
final PsiType type = invoked.getType();
if (type instanceof GrClosureType) {
elementToShow.add(type);
addSignatureVariant(elementToShow, (GrClosureType)type);
}
else if (type != null) {
final GroovyResolveResult[] calls = ResolveUtil.getMethodCandidates(type, "call", place, PsiUtil.getArgumentTypes(place, true));
elementToShow.addAll(ContainerUtil.findAll(calls, methodsOrClosures));
addMethodAndClosureVariants(elementToShow,
ResolveUtil.getMethodCandidates(type, "call", place, PsiUtil.getArgumentTypes(place, true)));
}
}
else {
elementToShow.addAll(ContainerUtil.findAll(variants, methodsOrClosures));
addMethodAndClosureVariants(elementToShow, variants);
}
}
else {
@@ -168,6 +160,30 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
context.showHint(place, place.getTextRange().getStartOffset(), this);
}
private static void addMethodAndClosureVariants(@NotNull List<Object> elementToShow, @NotNull GroovyResolveResult[] variants) {
for (GroovyResolveResult variant : variants) {
final PsiElement element = variant.getElement();
if (element instanceof PsiMethod) {
elementToShow.add(variant);
}
else if (element instanceof GrVariable) {
final PsiType type = ((GrVariable)element).getTypeGroovy();
if (type instanceof GrClosureType) {
addSignatureVariant(elementToShow, (GrClosureType)type);
}
}
}
}
private static void addSignatureVariant(@NotNull final List<Object> elementToShow, @NotNull GrClosureType type) {
type.getSignature().accept(new GrRecursiveSignatureVisitor() {
@Override
public void visitClosureSignature(GrClosureSignature signature) {
elementToShow.add(signature);
}
});
}
private static void filterOutReflectedMethods(List toShow) {
Set<GrMethod> methods = new HashSet<GrMethod>();
@@ -230,25 +246,21 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
}
argTypes = PsiUtil.getArgumentTypes(place, false);
}
else if (namedElement instanceof GrVariable) {
final PsiType type = ((GrVariable)namedElement).getTypeGroovy();
if (type instanceof GrClosureType) {
argTypes = PsiUtil.getArgumentTypes(place, false);
parameterTypes = ((GrClosureType)type).getClosureParameterTypes();
}
}
if (argTypes == null) continue;
}
else if (objects[i] instanceof GrClosureType) {
final GrClosureType type = (GrClosureType)objects[i];
else if (objects[i] instanceof GrClosureSignature) {
final GrClosureSignature signature = (GrClosureSignature)objects[i];
argTypes = PsiUtil.getArgumentTypes(place, false);
parameterTypes = type.getClosureParameterTypes();
parameterTypes = new PsiType[signature.getParameterCount()];
int j = 0;
for (GrClosureParameter parameter : signature.getParameters()) {
parameterTypes[j++] = parameter.getType();
}
}
else {
continue Outer;
}
assert parameterTypes != null;
assert argTypes != null;
if (parameterTypes.length <= currIndex) {
@@ -360,8 +372,8 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
return;
}
}
else if (o instanceof GrClosureType) {
if (!((GrClosureType)o).isValid()) {
else if (o instanceof GrClosureSignature) {
if (!((GrClosureSignature)o).isValid()) {
context.setUIComponentEnabled(false);
return;
}
@@ -374,6 +386,8 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
int highlightStartOffset = -1;
int highlightEndOffset = -1;
final int currentParameter = context.getCurrentParameterIndex();
StringBuilder buffer = new StringBuilder();
@@ -393,8 +407,6 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
buffer.append('(');
}
final int currentParameter = context.getCurrentParameterIndex();
final PsiParameter[] params = method.getParameterList().getParameters();
int numParams = params.length;
@@ -415,10 +427,7 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
}
if (context.isUIComponentEnabled() &&
(j == currentParameter ||
(j == numParams - 1 && param.isVarArgs() && currentParameter >= numParams)
)
) {
(j == currentParameter || (j == numParams - 1 && param.isVarArgs() && currentParameter >= numParams))) {
highlightStartOffset = startOffset;
highlightEndOffset = endOffset;
}
@@ -434,23 +443,37 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
} else if (element instanceof PsiClass) {
buffer.append("no parameters");
}
else if (element instanceof GrVariable) {
final PsiElement parent = context.getParameterOwner().getParent();
if (parent == null || !parent.isValid()) {
context.setUIComponentEnabled(false);
return;
}
final PsiType type;
if (parent instanceof GrMethodCallExpression) {
type = ((GrMethodCallExpression)parent).getInvokedExpression().getType();
else if (element instanceof GrClosureSignature) {
GrClosureParameter[] parameters = ((GrClosureSignature)element).getParameters();
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
if (i > 0) buffer.append(", ");
int startOffset = buffer.length();
final PsiType psiType = parameters[i].getType();
if (psiType == null) {
buffer.append("def");
}
else {
buffer.append(psiType.getPresentableText());
}
int endOffset = buffer.length();
if (context.isUIComponentEnabled() &&
(i == currentParameter || (i == parameters.length - 1 && ((GrClosureSignature)element).isVarargs() && currentParameter >= parameters.length))) {
highlightStartOffset = startOffset;
highlightEndOffset = endOffset;
}
final GrExpression initializer = parameters[i].getDefaultInitializer();
if (initializer != null) {
buffer.append(" = ").append(initializer.getText());
}
}
}
else {
type = ((GrVariable)element).getTypeGroovy();
buffer.append("no parameters");
}
generateForClosureType(buffer, type);
}
else if (element instanceof GrClosureType) {
generateForClosureType(buffer, (GrClosureType)element);
}
final boolean isDeprecated = o instanceof PsiDocCommentOwner && ((PsiDocCommentOwner) o).isDeprecated();
@@ -466,31 +489,6 @@ public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabAc
);
}
private static void generateForClosureType(StringBuilder buffer, PsiType type) {
if (type instanceof GrClosureType) {
GrClosureParameter[] parameters = ((GrClosureType)type).getSignature().getParameters();
if (parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
if (i > 0) buffer.append(", ");
final PsiType psiType = parameters[i].getType();
if (psiType == null) {
buffer.append("def");
}
else {
buffer.append(psiType.getPresentableText());
}
final GrExpression initializer = parameters[i].getDefaultInitializer();
if (initializer != null) {
buffer.append(" = ").append(initializer.getText());
}
}
}
else {
buffer.append("no parameters");
}
}
}
private static void appendParameterText(PsiParameter param, PsiSubstitutor substitutor, StringBuilder buffer) {
if (param instanceof GrParameter) {
GrParameter grParam = (GrParameter)param;
@@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocReferenceElement
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocTag;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -45,7 +46,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
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.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
@@ -13,17 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.api.types;
package org.jetbrains.plugins.groovy.lang.psi.api.signatures;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
/**
* @author Maxim.Medvedev
*/
public interface GrClosureSignature {
public interface GrClosureSignature extends GrSignature {
@NotNull PsiSubstitutor getSubstitutor();
@NotNull
@@ -36,8 +38,7 @@ public interface GrClosureSignature {
@Nullable
PsiType getReturnType();
@Nullable
GrCurriedClosureSignature curry(PsiType[] args, int position);
GrClosureSignature[] EMPTY_ARRAY = new GrClosureSignature[0];
boolean isValid();
boolean isCurried();
}
@@ -0,0 +1,49 @@
/*
* 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.api.signatures;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
/**
* @author Max Medvedev
*/
public interface GrMultiSignature extends GrSignature {
GrClosureSignature[] getAllSignatures();
GrMultiSignature EMPTY_SIGNATURE = new GrMultiSignature() {
@Override
public GrClosureSignature[] getAllSignatures() {
return GrClosureSignature.EMPTY_ARRAY;
}
@Override
public boolean isValid() {
return true;
}
@Override
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
return this;
}
@Override
public void accept(GrSignatureVisitor visitor) {
visitor.visitMultiSignature(this);
}
};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* 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.
@@ -13,23 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.api.types;
import com.intellij.psi.PsiType;
package org.jetbrains.plugins.groovy.lang.psi.api.signatures;
/**
* @author Maxim.Medvedev
* @author Max Medvedev
*/
public interface GrCurriedClosureSignature extends GrClosureSignature{
PsiType[] getCurriedArgs();
/**
*
* @return position or -1 if position is right
*/
int getCurriedPosition();
GrClosureSignature getOriginalSignature();
public abstract class GrRecursiveSignatureVisitor extends GrSignatureVisitor {
@Override
public void visitMultiSignature(GrMultiSignature signature) {
super.visitMultiSignature(signature);
for (GrClosureSignature s : signature.getAllSignatures()) {
s.accept(this);
}
}
}
@@ -0,0 +1,33 @@
/*
* 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.api.signatures;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
/**
* @author Max Medvedev
*/
public interface GrSignature {
boolean isValid();
@Nullable
GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context);
void accept(GrSignatureVisitor visitor);
}
@@ -0,0 +1,31 @@
/*
* 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.api.signatures;
/**
* @author Max Medvedev
*/
public abstract class GrSignatureVisitor {
public void visitClosureSignature(GrClosureSignature signature){
visitSignature(signature);
}
public void visitSignature(GrSignature signature){}
public void visitMultiSignature(GrMultiSignature signature){
visitSignature(signature);
}
}
@@ -22,18 +22,18 @@ import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
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.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.MixinTypeInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import static org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil.createSignature;
import static org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil.createSignature;
/**
* @author Max Medvedev
@@ -42,8 +42,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrM
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -23,24 +23,29 @@ import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
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.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.ArrayList;
import java.util.List;
/**
* @author ven
*/
public class GrClosureType extends GrLiteralClassType {
private final @NotNull GrClosureSignature mySignature;
private final @NotNull GrSignature mySignature;
private PsiType[] myTypeArgs = null;
private GrClosureType(LanguageLevel languageLevel,
GlobalSearchScope scope,
JavaPsiFacade facade,
@NotNull GrClosureSignature closureSignature,
@NotNull GrSignature closureSignature,
boolean shouldInferTypeParameters) {
super(languageLevel, scope, facade);
mySignature = closureSignature;
@@ -67,7 +72,8 @@ public class GrClosureType extends GrLiteralClassType {
if (myTypeArgs == null) {
final PsiClass psiClass = resolve();
if (psiClass != null && psiClass.getTypeParameters().length == 1) {
myTypeArgs = new PsiType[]{TypesUtil.boxPrimitiveType(mySignature.getReturnType(), getPsiManager(), getResolveScope(), true)};
final PsiType type = GrClosureSignatureUtil.getReturnType(mySignature);
myTypeArgs = new PsiType[]{TypesUtil.boxPrimitiveType(type, getPsiManager(), getResolveScope(), true)};
}
else {
myTypeArgs = PsiType.EMPTY_ARRAY;
@@ -76,6 +82,8 @@ public class GrClosureType extends GrLiteralClassType {
return myTypeArgs;
}
@NotNull
@Override
protected String getJavaClassName() {
@@ -108,7 +116,7 @@ public class GrClosureType extends GrLiteralClassType {
return super.equals(obj);
}
public boolean isAssignableFrom(@NotNull PsiType type) {
/*public boolean isAssignableFrom(@NotNull PsiType type) {
if (type instanceof GrClosureType) {
GrClosureType other = (GrClosureType)type;
GrClosureSignature otherSignature = other.mySignature;
@@ -137,7 +145,7 @@ public class GrClosureType extends GrLiteralClassType {
return true;
}
return super.isAssignableFrom(type);
}
}*/
public boolean equalsToText(@NonNls String text) {
return text.equals(GroovyCommonClassNames.GROOVY_LANG_CLOSURE);
@@ -150,6 +158,25 @@ public class GrClosureType extends GrLiteralClassType {
return result;
}
public static GrClosureType create(GroovyResolveResult[] results, GroovyPsiElement context) {
List<GrClosureSignature> signatures = new ArrayList<GrClosureSignature>();
for (GroovyResolveResult result : results) {
if (result.getElement() instanceof PsiMethod) {
signatures.add(GrClosureSignatureUtil.createSignature((PsiMethod)result.getElement(), result.getSubstitutor()));
}
}
final GlobalSearchScope resolveScope = context.getResolveScope();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(context.getProject());
if (signatures.size() == 1) {
return create(signatures.get(0), resolveScope, facade, LanguageLevel.JDK_1_5, true);
}
else {
return create(GrClosureSignatureUtil.createMultiSignature(signatures.toArray(new GrClosureSignature[signatures.size()])),
resolveScope, facade, LanguageLevel.JDK_1_5, true);
}
}
public static GrClosureType create(@NotNull GrClosableBlock closure, boolean shouldInferTypeParameters) {
final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(closure);
final GlobalSearchScope resolveScope = closure.getResolveScope();
@@ -172,7 +199,7 @@ public class GrClosureType extends GrLiteralClassType {
return create(GrClosureSignatureUtil.createSignature(parameters, returnType), scope, facade, languageLevel, true);
}
public static GrClosureType create(@NotNull GrClosureSignature signature,
public static GrClosureType create(@NotNull GrSignature signature,
GlobalSearchScope scope,
JavaPsiFacade facade,
LanguageLevel languageLevel,
@@ -181,8 +208,8 @@ public class GrClosureType extends GrLiteralClassType {
}
@Nullable
public PsiType curry(PsiType[] args, int position) {
final GrClosureSignature newSignature = mySignature.curry(args, position);
public PsiType curry(PsiType[] args, int position, GroovyPsiElement context) {
final GrSignature newSignature = mySignature.curry(args, position, context);
if (newSignature == null) return null;
final GrClosureType result = create(newSignature, myScope, myFacade, myLanguageLevel, true);
result.myTypeArgs = this.myTypeArgs;
@@ -190,16 +217,16 @@ public class GrClosureType extends GrLiteralClassType {
}
@NotNull
public GrClosureSignature getSignature() {
public GrSignature getSignature() {
return mySignature;
}
public PsiType[] getClosureParameterTypes() {
/*public PsiType[] getClosureParameterTypes() {
final GrClosureParameter[] parameters = mySignature.getParameters();
final PsiType[] types = new PsiType[parameters.length];
for (int i = 0; i < types.length; i++) {
types[i] = parameters[i].getType();
}
return types;
}
}*/
}
@@ -40,6 +40,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -55,7 +56,10 @@ 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.api.types.*;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClassTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
@@ -13,22 +13,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
package org.jetbrains.plugins.groovy.lang.psi.impl.signatures;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrMultiSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignatureVisitor;
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.api.types.GrCurriedClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureParameterImpl;
import java.util.ArrayList;
import java.util.List;
/**
* @author Maxim.Medvedev
*/
public class GrClosureSignatureImpl implements GrClosureSignature {
private final boolean myIsVarargs;
private final boolean myCurried;
@Nullable private final PsiType myReturnType;
@NotNull private final GrClosureParameter[] myParameters;
@NotNull private final PsiSubstitutor mySubstitutor;
@@ -47,20 +55,21 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
myIsVarargs = false;
}
mySubstitutor = substitutor;
myCurried = false;
}
public GrClosureSignatureImpl(PsiParameter[] parameters, @Nullable PsiType returnType) {
this(parameters, returnType, PsiSubstitutor.EMPTY);
}
GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs) {
GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs, boolean isCurried) {
myParameters = params;
myReturnType = returnType;
myIsVarargs = isVarArgs;
myCurried = isCurried;
mySubstitutor = PsiSubstitutor.EMPTY;
}
public boolean isVarargs() {
return myIsVarargs;
}
@@ -89,8 +98,44 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
}
@Nullable
public GrCurriedClosureSignature curry(PsiType[] args, int position) {
return new GrCurriedClosureSignatureImpl(this, args, position);
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
GrClosureParameter[] params = myParameters;
List<GrClosureParameter> newParams = new ArrayList<GrClosureParameter>(params.length);
List<GrClosureParameter> opts = new ArrayList<GrClosureParameter>(params.length);
List<Integer> optInds = new ArrayList<Integer>(params.length);
if (position == -1) {
position = params.length - args.length;
}
if (position < 0 || position >= params.length) return GrMultiSignature.EMPTY_SIGNATURE;
for (int i = 0; i < params.length; i++) {
if (params[i].isOptional()) {
opts.add(params[i]);
optInds.add(i);
}
else {
newParams.add(params[i]);
}
}
final PsiType rtype = getReturnType();
final ArrayList<GrClosureSignature> result = new ArrayList<GrClosureSignature>();
GrClosureSignatureUtil.checkAndAddSignature(result, args, position, newParams, rtype, context);
for (int i = 0; i < opts.size(); i++) {
newParams.add(optInds.get(i), opts.get(i));
GrClosureSignatureUtil.checkAndAddSignature(result, args, position, newParams, rtype, context);
}
if (result.size() == 1) {
return result.get(0);
}
else {
return new GrMultiSignatureImpl(result.toArray(new GrClosureSignature[result.size()]));
}
}
public boolean isValid() {
@@ -110,6 +155,10 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
return super.equals(obj);
}
public boolean isCurried() {
return myCurried;
}
@Nullable
public static GrClosureSignature getLeastUpperBound(@NotNull GrClosureSignature signature1,
@NotNull GrClosureSignature signature2,
@@ -131,10 +180,15 @@ public class GrClosureSignatureImpl implements GrClosureSignature {
returnType = TypesUtil.getLeastUpperBound(s1type, s2type, manager);
}
boolean isVarArgs = signature1.isVarargs() && signature2.isVarargs();
return new GrClosureSignatureImpl(params, returnType, isVarArgs);
return new GrClosureSignatureImpl(params, returnType, isVarArgs, false);
}
return null; //todo
}
@Override
public void accept(GrSignatureVisitor visitor) {
visitor.visitClosureSignature(this);
}
}
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
package org.jetbrains.plugins.groovy.lang.psi.impl.signatures;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
@@ -30,6 +31,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrMultiSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrRecursiveSignatureVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
@@ -39,12 +44,11 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExp
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
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.api.types.GrCurriedClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrMapType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureParameterImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.*;
@@ -57,13 +61,24 @@ public class GrClosureSignatureUtil {
private GrClosureSignatureUtil() {
}
public static GrMultiSignature createMultiSignature(GrClosureSignature[] signatures) {
return new GrMultiSignatureImpl(signatures);
}
@Nullable
public static GrClosureSignature createSignature(GrCall call) {
if (call instanceof GrMethodCall) {
final GrExpression invokedExpression = ((GrMethodCall)call).getInvokedExpression();
final PsiType type = invokedExpression.getType();
if (type instanceof GrClosureType) return ((GrClosureType)type).getSignature();
if (type instanceof GrClosureType) {
final GrSignature signature = ((GrClosureType)type).getSignature();
final Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult> trinity =
getApplicableSignature(signature, PsiUtil.getArgumentTypes(invokedExpression, true), call);
if (trinity != null) {
return trinity.first;
}
return null;
}
}
final GroovyResolveResult resolveResult = call.advancedResolve();
@@ -105,7 +120,7 @@ public class GrClosureSignatureUtil {
public static GrClosureSignature removeParam(final GrClosureSignature signature, int i) {
final GrClosureParameter[] newParams = ArrayUtil.remove(signature.getParameters(), i);
return new GrClosureSignatureImpl(newParams, null, newParams.length > 0 && signature.isVarargs()) {
return new GrClosureSignatureImpl(newParams, null, newParams.length > 0 && signature.isVarargs(), false) {
@Override
public PsiType getReturnType() {
return signature.getReturnType();
@@ -127,7 +142,7 @@ public class GrClosureSignatureUtil {
closureParams[i] = new GrClosureParameterImpl(type, GrClosureParameterImpl.isParameterOptional(param),
GrClosureParameterImpl.getDefaultInitializer(param));
}
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams)) {
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams), false) {
@Override
public PsiType getReturnType() {
return PsiUtil.getSmartReturnType(method);
@@ -149,7 +164,7 @@ public class GrClosureSignatureUtil {
closureParams[i] = new GrClosureParameterImpl(type, GrClosureParameterImpl.isParameterOptional(param),
GrClosureParameterImpl.getDefaultInitializer(param));
}
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams)) {
return new GrClosureSignatureImpl(closureParams, null, GrClosureParameterImpl.isVararg(closureParams), false) {
@Override
public PsiType getReturnType() {
return closure.getReturnType();
@@ -167,26 +182,131 @@ public class GrClosureSignatureUtil {
return new GrClosureSignatureImpl(parameters, returnType);
}
public static boolean isSignatureApplicable(@NotNull GrClosureSignature signature, @NotNull PsiType[] args, @NotNull GroovyPsiElement context) {
@Nullable
public static PsiType getReturnType(@NotNull final GrSignature signature, @NotNull GrMethodCall expr) {
return getReturnType(signature, PsiUtil.getArgumentTypes(expr.getInvokedExpression(), true), expr);
}
@Nullable
public static PsiType getReturnType(@NotNull final GrSignature signature, @Nullable PsiType[] args, @NotNull GroovyPsiElement context) {
if (signature instanceof GrClosureSignature) return ((GrClosureSignature)signature).getReturnType();
if (args == null) {
return TypesUtil.getLeastUpperBoundNullable(new Iterable<PsiType>() {
@Override
public Iterator<PsiType> iterator() {
return new Iterator<PsiType>() {
private final Iterator<GrClosureSignature> it = Arrays.asList(((GrMultiSignature)signature).getAllSignatures()).iterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public PsiType next() {
return it.next().getReturnType();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}, context.getManager());
}
final List<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> results =
getSignatureApplicabilities(signature, args, context);
if (results.size() == 1) return results.get(0).first.getReturnType();
return TypesUtil.getLeastUpperBoundNullable(new Iterable<PsiType>() {
@Override
public Iterator<PsiType> iterator() {
return new Iterator<PsiType>() {
private final Iterator<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> myIterator = results.iterator();
@Override
public boolean hasNext() {
return myIterator.hasNext();
}
@Override
public PsiType next() {
return myIterator.next().first.getReturnType();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}, context.getManager());
}
public static boolean isSignatureApplicable(@NotNull GrSignature signature, @NotNull PsiType[] args, @NotNull GroovyPsiElement context) {
return isSignatureApplicableConcrete(signature, args, context) != ApplicabilityResult.inapplicable;
}
public static ApplicabilityResult isSignatureApplicableConcrete(@NotNull GrClosureSignature signature, @NotNull PsiType[] args, @NotNull GroovyPsiElement context) {
ArgInfo<PsiType>[] map = mapArgTypesToParameters(signature, args, context, false);
if (map != null) return isSignatureApplicableInner(map, signature);
public static ApplicabilityResult isSignatureApplicableConcrete(@NotNull GrSignature signature, @NotNull final PsiType[] args, @NotNull final GroovyPsiElement context) {
final List<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> results =
getSignatureApplicabilities(signature, args, context);
// check for the case foo([1, 2, 3]) if foo(int, int, int)
if (args.length == 1 && PsiUtil.isInMethodCallContext(context)) {
final GrClosureParameter[] parameters = signature.getParameters();
if (parameters.length == 1 && parameters[0].getType() instanceof PsiArrayType) return ApplicabilityResult.inapplicable;
PsiType arg = args[0];
if (arg instanceof GrTupleType) {
args = ((GrTupleType)arg).getComponentTypes();
map = mapArgTypesToParameters(signature, args, context, false);
if (map != null) return isSignatureApplicableInner(map, signature);
if (results.isEmpty()) return ApplicabilityResult.inapplicable;
else if (results.size()==1) return results.get(0).third;
else return ApplicabilityResult.ambiguous;
}
@Nullable
public static Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult> getApplicableSignature(@NotNull GrSignature signature,
@Nullable final PsiType[] args,
@NotNull final GroovyPsiElement context) {
if (args == null) return null;
final List<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> results = getSignatureApplicabilities(signature, args, context);
if (results.size() == 1) return results.get(0);
else return null;
}
private static List<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> getSignatureApplicabilities(@NotNull GrSignature signature,
@NotNull final PsiType[] args,
@NotNull final GroovyPsiElement context) {
final List<Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>> results =
new ArrayList<Trinity<GrClosureSignature, GrClosureSignatureUtil.ArgInfo<PsiType>[], ApplicabilityResult>>();
signature.accept(new GrRecursiveSignatureVisitor() {
@Override
public void visitClosureSignature(GrClosureSignature signature) {
ArgInfo<PsiType>[] map = mapArgTypesToParameters(signature, args, context, false);
if (map != null) {
results.add(new Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>(signature, map, isSignatureApplicableInner(map, signature)));
return;
}
// check for the case foo([1, 2, 3]) if foo(int, int, int)
if (args.length == 1 && PsiUtil.isInMethodCallContext(context)) {
final GrClosureParameter[] parameters = signature.getParameters();
if (parameters.length == 1 && parameters[0].getType() instanceof PsiArrayType) {
return;
}
PsiType arg = args[0];
if (arg instanceof GrTupleType) {
PsiType[] _args = ((GrTupleType)arg).getComponentTypes();
map = mapArgTypesToParameters(signature, _args, context, false);
if (map != null) {
results.add(new Trinity<GrClosureSignature, ArgInfo<PsiType>[], ApplicabilityResult>(signature, map,
isSignatureApplicableInner(map,
signature)));
}
}
}
}
}
return ApplicabilityResult.inapplicable;
});
return results;
}
private static ApplicabilityResult isSignatureApplicableInner(@NotNull ArgInfo<PsiType>[] infos, @NotNull GrClosureSignature signature) {
@@ -206,10 +326,10 @@ public class GrClosureSignatureUtil {
}
public enum ApplicabilityResult {
applicable, inapplicable, canBeApplicable;
applicable, inapplicable, canBeApplicable, ambiguous;
public static boolean isApplicable(ApplicabilityResult r) {
return r != inapplicable;
return r != inapplicable && r!= ambiguous;
}
}
@@ -240,61 +360,12 @@ public class GrClosureSignatureUtil {
};
}
@Nullable
private static <Arg> ArgWrapper<Arg>[] getActualArgs(@NotNull GrCurriedClosureSignature signature,
@NotNull Arg[] args,
@NotNull Function<Arg, PsiType> typeComputer) {
List<ArgWrapper<Arg>> actual = new ArrayList<ArgWrapper<Arg>>(signature.getParameterCount());
for (Arg arg : args) {
actual.add(new ArgWrapper<Arg>(typeComputer.fun(arg), arg));
}
GrCurriedClosureSignature curried = signature;
while (true) {
final PsiType[] curriedArgs = curried.getCurriedArgs();
int curriedPosition = curried.getCurriedPosition();
if (curriedPosition == -1) curriedPosition = actual.size();
if (curriedPosition > actual.size()) return null;
for (int i = 0; i < curriedArgs.length; i++, curriedPosition++) {
actual.add(curriedPosition, new ArgWrapper<Arg>(curriedArgs[i], null));
}
if (!(curried.getOriginalSignature() instanceof GrCurriedClosureSignature)) break;
curried = (GrCurriedClosureSignature)curried.getOriginalSignature();
}
return actual.toArray(new ArgWrapper[args.length]);
}
public static GrClosureSignature getOriginalSignature(GrClosureSignature signature) {
if (signature instanceof GrCurriedClosureSignature) {
return getOriginalSignature(((GrCurriedClosureSignature)signature).getOriginalSignature());
}
return signature;
}
@Nullable
private static <Arg> ArgInfo<Arg>[] mapParametersToArguments(@NotNull GrClosureSignature signature,
@NotNull Arg[] args,
@NotNull Function<Arg, PsiType> typeComputer,
@NotNull GroovyPsiElement context,
boolean partial) {
if (signature instanceof GrCurriedClosureSignature) {
final ArgWrapper<Arg>[] actualArgs = getActualArgs((GrCurriedClosureSignature)signature, args, typeComputer);
if (actualArgs == null) return null;
final ArgInfo<ArgWrapper<Arg>>[] argInfos =
mapParametersToArguments(getOriginalSignature(signature), actualArgs, GrClosureSignatureUtil.<Arg>ARG_WRAPPER_COMPUTER(), context, partial);
if (argInfos == null) return null;
final ArgInfo<Arg>[] result = new ArgInfo[argInfos.length];
for (int i = 0; i < argInfos.length; i++) {
ArgInfo<ArgWrapper<Arg>> info = argInfos[i];
List<Arg> list = new ArrayList<Arg>();
for (ArgWrapper<Arg> arg : info.args) {
if (arg.arg != null) list.add(arg.arg);
}
result[i] = new ArgInfo<Arg>(list, info.isMultiArg);
}
return result;
}
if (checkForOnlyMapParam(signature, args.length)) return ArgInfo.empty_array();
GrClosureParameter[] params = signature.getParameters();
if (args.length > params.length && !signature.isVarargs()) return null;
@@ -313,7 +384,7 @@ public class GrClosureSignatureUtil {
}
private static boolean checkForOnlyMapParam(@NotNull GrClosureSignature signature, final int argCount) {
if (argCount > 0) return false;
if (argCount > 0 || signature.isCurried()) return false;
final GrClosureParameter[] parameters = signature.getParameters();
if (parameters.length != 1) return false;
final PsiType type = parameters[0].getType();
@@ -352,6 +423,33 @@ public class GrClosureSignatureUtil {
return TypesUtil.isAssignableByMethodCallConversion(paramType, argType, context);
}
public static void checkAndAddSignature(List<GrClosureSignature> list,
PsiType[] args,
int position,
List<GrClosureParameter> params,
PsiType returnType,
@NotNull GroovyPsiElement context) {
final int last = position + args.length;
if (last > params.size()) return;
for (int i = position; i < last; i++) {
final GrClosureParameter p = params.get(i);
final PsiType type = p.getType();
if (!isAssignableByConversion(type, args[i - position], context)) return;
}
GrClosureParameter[] _p = new GrClosureParameter[params.size() - args.length];
int j = 0;
for (int i = 0; i < position; i++) {
_p[j++] = params.get(i);
}
for (int i = position + args.length; i < params.size(); i++) {
_p[j++] = params.get(i);
}
list.add(new GrClosureSignatureImpl(_p, returnType, _p.length > 0 && _p[_p.length - 1].getType() instanceof PsiArrayType, true));
}
@Nullable
public static GrClosureSignature createSignature(GroovyResolveResult resolveResult) {
final PsiElement resolved = resolveResult.getElement();
@@ -626,7 +724,9 @@ public class GrClosureSignatureUtil {
String name = method.getName();
PsiTypeParameter[] typeParameters = method.getTypeParameters();
return generateAllMethodSignaturesByClosureSignature(name, signature, typeParameters, substitutor);
final ArrayList<MethodSignature> result = new ArrayList<MethodSignature>();
generateAllMethodSignaturesByClosureSignature(name, signature, typeParameters, substitutor, result);
return result;
}
public static MultiMap<MethodSignature, PsiMethod> findMethodSignatures(PsiMethod[] methods) {
@@ -646,10 +746,11 @@ public class GrClosureSignatureUtil {
return MethodSignatureUtil.createMethodSignature(name, paramTypes.toArray(new PsiType[paramTypes.size()]), typeParameters, substitutor);
}
public static List<MethodSignature> generateAllMethodSignaturesByClosureSignature(@NotNull String name,
@NotNull GrClosureSignature signature,
@NotNull PsiTypeParameter[] typeParameters,
@NotNull PsiSubstitutor substitutor) {
public static void generateAllMethodSignaturesByClosureSignature(@NotNull String name,
@NotNull GrClosureSignature signature,
@NotNull PsiTypeParameter[] typeParameters,
@NotNull PsiSubstitutor substitutor,
List<MethodSignature> result) {
GrClosureParameter[] params = signature.getParameters();
ArrayList<PsiType> newParams = new ArrayList<PsiType>(params.length);
@@ -666,18 +767,24 @@ public class GrClosureSignatureUtil {
}
}
List<MethodSignature> result = new ArrayList<MethodSignature>(opts.size() + 1);
result.add(generateSignature(name, newParams, typeParameters, substitutor));
for (int i = 0; i < opts.size(); i++) {
newParams.add(optInds.get(i), opts.get(i).getType());
result.add(generateSignature(name, newParams, typeParameters, substitutor));
}
return result;
}
public static List<MethodSignature> generateAllMethodSignaturesByClosureSignature(@NotNull String name,
@NotNull GrClosureSignature signature) {
return generateAllMethodSignaturesByClosureSignature(name, signature, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
public static List<MethodSignature> generateAllMethodSignaturesBySignature(@NotNull final String name,
@NotNull final GrSignature signature) {
final ArrayList<MethodSignature> result = new ArrayList<MethodSignature>();
signature.accept(new GrRecursiveSignatureVisitor() {
@Override
public void visitClosureSignature(GrClosureSignature signature) {
generateAllMethodSignaturesByClosureSignature(name, signature, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, result);
}
});
return result;
}
@Nullable
@@ -713,4 +820,31 @@ public class GrClosureSignatureUtil {
}
}
/**
*
* @param signature
* @return return type or null if there is some different return types
*/
@Nullable
public static PsiType getReturnType(GrSignature signature) {
if (signature instanceof GrClosureSignature) {
return ((GrClosureSignature)signature).getReturnType();
}
else if (signature instanceof GrMultiSignature) {
final GrClosureSignature[] signatures = ((GrMultiSignature)signature).getAllSignatures();
if (signatures.length == 0) return null;
final PsiType type = signatures[0].getReturnType();
if (type == null) return null;
String firstType = type.getCanonicalText();
for (int i = 1; i < signatures.length; i++) {
final PsiType _type = signatures[i].getReturnType();
if (_type == null) return null;
if (!firstType.equals(_type.getCanonicalText())) return null;
}
return type;
}
return null;
}
}
@@ -0,0 +1,73 @@
/*
* 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.signatures;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrMultiSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignatureVisitor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Max Medvedev
*/
public class GrMultiSignatureImpl implements GrMultiSignature {
private final GrClosureSignature[] mySignatures;
public GrMultiSignatureImpl(GrClosureSignature[] signatures) {
mySignatures = signatures;
}
@Override
public GrClosureSignature[] getAllSignatures() {
return mySignatures;
}
@Override
public boolean isValid() {
for (GrClosureSignature signature : mySignatures) {
if (!signature.isValid()) return false;
}
return true;
}
@Override
public GrSignature curry(@NotNull PsiType[] args, int position, @NotNull GroovyPsiElement context) {
List<GrClosureSignature> newClosures = new ArrayList<GrClosureSignature>();
for (GrClosureSignature old : mySignatures) {
final GrSignature curried = old.curry(args, position, context);
if (curried instanceof GrClosureSignature) {
newClosures.add((GrClosureSignature)curried);
}
else if (curried instanceof GrMultiSignature) {
newClosures.addAll(Arrays.asList(((GrMultiSignature)curried).getAllSignatures()));
}
}
return new GrMultiSignatureImpl(newClosures.toArray(new GrClosureSignature[newClosures.size()]));
}
@Override
public void accept(GrSignatureVisitor visitor) {
visitor.visitMultiSignature(this);
}
}
@@ -62,7 +62,7 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs
PsiType returnType = null;
final PsiManager manager = assignment.getManager();
for (GroovyResolveResult result : results) {
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(result, assignment);
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(result, assignment, new PsiType[]{getRValueType(assignment)});
returnType = TypesUtil.getLeastUpperBoundNullable(returnType, substituted, manager);
}
return returnType;
@@ -218,12 +218,16 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs
}
if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
final GrExpression rightOperand = assignmentExpression.getRValue();
PsiType rType = rightOperand == null ? null : rightOperand.getType();
PsiType rType = getRValueType(assignmentExpression);
final IElementType operatorToken = TokenSets.ASSIGNMENTS_TO_OPERATORS.get(opType);
return TypesUtil.getOverloadedOperatorCandidates(lType, operatorToken, assignmentExpression, new PsiType[]{rType});
}
};
@Nullable
private static PsiType getRValueType(GrAssignmentExpressionImpl assignmentExpression) {
final GrExpression rightOperand = assignmentExpression.getRValue();
return rightOperand == null ? null : rightOperand.getType();
}
}
@@ -51,12 +51,17 @@ public abstract class GrBinaryExpressionImpl extends GrExpressionImpl implements
final PsiType lType = binary.getLeftOperand().getType();
if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
final GrExpression rightOperand = binary.getRightOperand();
PsiType rType = rightOperand == null ? null : rightOperand.getType();
PsiType rType = getRightType(binary);
return TypesUtil.getOverloadedOperatorCandidates(lType, opType, binary, new PsiType[]{rType});
}
};
@Nullable
private static PsiType getRightType(GrBinaryExpressionImpl binary) {
final GrExpression rightOperand = binary.getRightOperand();
return rightOperand == null ? null : rightOperand.getType();
}
private static final Function<GrBinaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
@Nullable
@Override
@@ -68,7 +73,7 @@ public abstract class GrBinaryExpressionImpl extends GrExpressionImpl implements
}
final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(binary.multiResolve(false));
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, binary);
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, binary, new PsiType[]{getRightType(binary)});
return TypesUtil.boxPrimitiveType(substituted, binary.getManager(), binary.getResolveScope());
}
};
@@ -487,10 +487,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
if (dotType == mMEMBER_POINTER) {
if (resolved instanceof PsiMethod) {
return GrClosureType.create((PsiMethod) resolved, resolveResult.getSubstitutor());
}
return TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.GROOVY_LANG_CLOSURE, this);
return GrClosureType.create(multiResolve(false), this);
}
PsiType result = null;
JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
@@ -35,11 +35,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.util.LightCacheKey;
@@ -482,15 +483,18 @@ public class TypesUtil {
else if (type1 instanceof GrClosureType && type2 instanceof GrClosureType) {
GrClosureType clType1 = (GrClosureType)type1;
GrClosureType clType2 = (GrClosureType)type2;
GrClosureSignature signature1 = clType1.getSignature();
GrClosureSignature signature2 = clType2.getSignature();
GrSignature signature1 = clType1.getSignature();
GrSignature signature2 = clType2.getSignature();
if (signature1.getParameterCount() == signature2.getParameterCount()) {
final GrClosureSignature signature = GrClosureSignatureImpl.getLeastUpperBound(signature1, signature2, manager);
if (signature != null) {
GlobalSearchScope scope = clType1.getResolveScope().intersectWith(clType2.getResolveScope());
final LanguageLevel languageLevel = ComparatorUtil.max(clType1.getLanguageLevel(), clType2.getLanguageLevel());
return GrClosureType.create(signature, scope, JavaPsiFacade.getInstance(manager.getProject()), languageLevel, true);
if (signature1 instanceof GrClosureSignature && signature2 instanceof GrClosureSignature) {
if (((GrClosureSignature)signature1).getParameterCount() == ((GrClosureSignature)signature2).getParameterCount()) {
final GrClosureSignature signature = GrClosureSignatureImpl.getLeastUpperBound(((GrClosureSignature)signature1),
((GrClosureSignature)signature2), manager);
if (signature != null) {
GlobalSearchScope scope = clType1.getResolveScope().intersectWith(clType2.getResolveScope());
final LanguageLevel languageLevel = ComparatorUtil.max(clType1.getLanguageLevel(), clType2.getLanguageLevel());
return GrClosureType.create(signature, scope, JavaPsiFacade.getInstance(manager.getProject()), languageLevel, true);
}
}
}
}
@@ -58,7 +58,7 @@ public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryEx
if (opType == null) return null;
final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(unary.multiResolve(false));
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, unary);
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, unary, PsiType.EMPTY_ARRAY);
if (substituted != null) {
return TypesUtil.boxPrimitiveType(substituted, unary.getManager(), unary.getResolveScope());
}
@@ -31,6 +31,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrLiteralClassType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrCallExpressionTypeCalculator;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -99,7 +100,7 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
private static PsiType extractReturnTypeFromType(PsiType type, boolean returnTypeIfFail, GrMethodCall callExpression) {
PsiType returnType = returnTypeIfFail ? type: null;
if (type instanceof GrClosureType) {
returnType = ((GrClosureType) type).getSignature().getReturnType();
returnType = GrClosureSignatureUtil.getReturnType(((GrClosureType)type).getSignature(), callExpression);
}
else if (isPsiClassTypeToClosure(type)) {
assert type instanceof PsiClassType;
@@ -114,7 +115,7 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
returnType = null;
final PsiManager manager = callExpression.getManager();
for (GroovyResolveResult call : calls) {
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(call, callExpression);
final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(call, callExpression, PsiUtil.getArgumentTypes(callExpression.getInvokedExpression(), true));
returnType = TypesUtil.getLeastUpperBoundNullable(returnType, substituted, manager);
}
}
@@ -154,16 +155,16 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
if (!(qType instanceof GrClosureType)) return null;
if ("call".equals(resolved.getName())) {
return ((GrClosureType)qType).getSignature().getReturnType();
return GrClosureSignatureUtil.getReturnType(((GrClosureType)qType).getSignature(), callExpression);
}
else if ("curry".equals(resolved.getName()) || "trampoline".equals(resolved.getName())) {
return ((GrClosureType)qType).curry(PsiUtil.getArgumentTypes(refExpr, false), 0);
return ((GrClosureType)qType).curry(PsiUtil.getArgumentTypes(refExpr, false), 0, callExpression);
}
else if ("memoize".equals(resolved.getName())) {
return qType;
}
else if ("rcurry".equals(resolved.getName())) {
return ((GrClosureType)qType).curry(PsiUtil.getArgumentTypes(refExpr, false), -1);
return ((GrClosureType)qType).curry(PsiUtil.getArgumentTypes(refExpr, false), -1, callExpression);
}
else if ("ncurry".equals(resolved.getName())) {
final GrArgumentList argList = callExpression.getArgumentList();
@@ -176,7 +177,7 @@ public class DefaultCallExpressionTypeCalculator extends GrCallExpressionTypeCal
if (value instanceof Integer) {
final PsiType[] argTypes = PsiUtil.getArgumentTypes(refExpr, false);
if (argTypes != null) {
return ((GrClosureType)qType).curry(ArrayUtil.remove(argTypes, 0), (Integer)value);
return ((GrClosureType)qType).curry(ArrayUtil.remove(argTypes, 0), (Integer)value, callExpression);
}
}
}
@@ -101,9 +101,21 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp
}
final GroovyResolveResult[] candidates = index.multiResolve(false);
PsiType overloadedOperatorType = ResolveUtil.extractReturnTypeFromCandidate(PsiImplUtil.extractUniqueResult(candidates), index);
PsiType componentType = extractMapValueType(thisType, argTypes, manager, resolveScope);
PsiType[] args = PsiUtil
.getArgumentTypes(argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, true, null);
final GroovyResolveResult candidate = PsiImplUtil.extractUniqueResult(candidates);
final PsiElement element = candidate.getElement();
if (element instanceof PsiNamedElement) {
final String name = ((PsiNamedElement)element).getName();
if ("putAt".equals(name) && args != null) {
args = ArrayUtil.append(args, TypeInferenceHelper.getInitializerFor(index), PsiType.class);
}
}
PsiType overloadedOperatorType = ResolveUtil.extractReturnTypeFromCandidate(candidate, index, args);
PsiType componentType = extractMapValueType(thisType, args, manager, resolveScope);
if (overloadedOperatorType != null &&
(componentType == null || !TypesUtil.isAssignable(overloadedOperatorType, componentType, manager, resolveScope))) {
@@ -1,88 +0,0 @@
/*
* Copyright 2000-2011 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.types;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
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.api.types.GrCurriedClosureSignature;
public class GrCurriedClosureSignatureImpl implements GrCurriedClosureSignature {
private final GrClosureSignature myOriginal;
private final PsiType[] myArgs;
private final int myPosition;
public GrCurriedClosureSignatureImpl(GrClosureSignature original, PsiType[] args, int position) {
myOriginal = original;
myArgs = args;
myPosition = position;
}
@Override
public PsiType getReturnType() {
return myOriginal.getReturnType();
}
@Override
public PsiType[] getCurriedArgs() {
return myArgs;
}
@Override
public int getCurriedPosition() {
return myPosition;
}
@Override
public GrClosureSignature getOriginalSignature() {
return myOriginal;
}
@NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return myOriginal.getSubstitutor();
}
@NotNull
@Override
public GrClosureParameter[] getParameters() {
return myOriginal.getParameters();
}
@Override
public int getParameterCount() {
return myOriginal.getParameterCount();
}
@Override
public boolean isVarargs() {
return myOriginal.isVarargs();
}
@Override
public GrCurriedClosureSignature curry(PsiType[] args, int position) {
return new GrCurriedClosureSignatureImpl(this, args, position);
}
@Override
public boolean isValid() {
return myOriginal.isValid();
}
}
@@ -21,6 +21,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
@@ -51,6 +52,8 @@ import org.jetbrains.plugins.groovy.lang.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -70,14 +73,13 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrMemberOwne
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrNamedArgumentsOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.JavaIdentifier;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
@@ -194,7 +196,7 @@ public class PsiUtil {
GroovyPsiElement context) {
if (argumentTypes == null) return GrClosureSignatureUtil.ApplicabilityResult.canBeApplicable;
GrClosureSignature signature = type.getSignature();
GrSignature signature = type.getSignature();
return GrClosureSignatureUtil.isSignatureApplicableConcrete(signature, argumentTypes, context);
}
@@ -603,8 +605,7 @@ public class PsiUtil {
final GrExpression expression = call.getInvokedExpression();
if (expression instanceof GrReferenceExpression && result.isInvokedOnProperty()) {
if (returnType instanceof GrClosureType) {
final GrClosureSignature signature = ((GrClosureType)returnType).getSignature();
return isRawType(signature.getReturnType(), TypesUtil.composeSubstitutors(signature.getSubstitutor(), result.getSubstitutor()));
return isRawClosureCall(call, result, (GrClosureType)returnType);
}
}
else {
@@ -614,14 +615,31 @@ public class PsiUtil {
if (element instanceof PsiVariable) {
final PsiType type = call.getInvokedExpression().getType();
if (type instanceof GrClosureType) {
final GrClosureSignature signature = ((GrClosureType)type).getSignature();
return isRawType(signature.getReturnType(), TypesUtil.composeSubstitutors(signature.getSubstitutor(), result.getSubstitutor()));
return isRawClosureCall(call, result, (GrClosureType)type);
}
}
return false;
}
private static boolean isRawClosureCall(GrMethodCallExpression call, GroovyResolveResult result, GrClosureType returnType) {
final GrSignature signature = returnType.getSignature();
GrClosureSignature _signature;
if (signature instanceof GrClosureSignature) {
_signature = (GrClosureSignature)signature;
}
else {
final PsiType[] types = getArgumentTypes(call.getInvokedExpression(), true);
final Trinity<GrClosureSignature, GrClosureSignatureUtil.ArgInfo<PsiType>[], GrClosureSignatureUtil.ApplicabilityResult>
resultTrinity = types != null ? GrClosureSignatureUtil.getApplicableSignature(signature, types, call) : null;
_signature = resultTrinity != null ? resultTrinity.first : null;
}
if (_signature != null) {
return isRawType(_signature.getReturnType(), TypesUtil.composeSubstitutors(_signature.getSubstitutor(), result.getSubstitutor()));
}
return false;
}
public static boolean isRawFieldAccess(GrReferenceExpression ref) {
PsiElement element = null;
final GroovyResolveResult[] resolveResults = ref.multiResolve(false);
@@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
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.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -51,11 +52,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousC
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
@@ -679,12 +679,12 @@ public class ResolveUtil {
private static boolean isApplicableClosureType(PsiType type, PsiType[] argTypes, GroovyPsiElement place) {
if (!(type instanceof GrClosureType)) return false;
final GrClosureSignature signature = ((GrClosureType)type).getSignature();
final GrSignature signature = ((GrClosureType)type).getSignature();
return GrClosureSignatureUtil.isSignatureApplicable(signature, argTypes, place);
}
@Nullable
public static PsiType extractReturnTypeFromCandidate(GroovyResolveResult candidate, GrExpression expression) {
public static PsiType extractReturnTypeFromCandidate(GroovyResolveResult candidate, GrExpression expression, @Nullable PsiType[] args) {
final PsiElement element = candidate.getElement();
if (element instanceof PsiMethod && !candidate.isInvokedOnProperty()) {
return TypesUtil.substituteBoxAndNormalizeType(getSmartReturnType((PsiMethod)element), candidate.getSubstitutor(), expression);
@@ -701,7 +701,8 @@ public class ResolveUtil {
return null;
}
if (type instanceof GrClosureType) {
PsiType returnType = ((GrClosureType)type).getSignature().getReturnType();
final GrSignature signature = ((GrClosureType)type).getSignature();
PsiType returnType = GrClosureSignatureUtil.getReturnType(signature, args, expression);
return TypesUtil.substituteBoxAndNormalizeType(returnType, candidate.getSubstitutor(), expression);
}
return null;
@@ -27,12 +27,12 @@ import org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider;
import org.jetbrains.plugins.groovy.gpp.GppTypeConverter;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrGdkMethodImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrClassInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -37,9 +38,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
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;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
@@ -68,8 +68,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator;
@@ -27,11 +27,11 @@ import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage;
import com.intellij.usageView.UsageInfo;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
/**
@@ -20,14 +20,15 @@ import com.intellij.psi.util.MethodSignature;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrRecursiveSignatureVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
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.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
@@ -45,18 +46,18 @@ public class GrMethodConflictUtil {
GrMethod refactoredMethod,
final MultiMap<PsiElement, String> conflicts, boolean excludeJavaConflicts) {
List<MethodSignature> prototypeSignatures = GrClosureSignatureUtil.generateAllSignaturesForMethod(prototype, PsiSubstitutor.EMPTY);
checkForClosurePropertySignatrureOverload(clazz, prototype, refactoredMethod, conflicts, prototypeSignatures);
checkForClosurePropertySignatureOverload(clazz, prototype, refactoredMethod, conflicts, prototypeSignatures);
checkForMethodSignatureOverload(clazz, prototype, refactoredMethod, conflicts, excludeJavaConflicts, prototypeSignatures);
checkForAccessorOverloading(clazz, prototype, conflicts);
}
private static void checkForClosurePropertySignatrureOverload(PsiClass clazz,
GrMethod prototype,
GrMethod refactoredMethod,
MultiMap<PsiElement, String> conflicts,
List<MethodSignature> prototypeSignatures) {
final boolean isStatic = prototype.hasModifierProperty(GrModifier.STATIC);
private static void checkForClosurePropertySignatureOverload(PsiClass clazz,
GrMethod prototype,
final GrMethod refactoredMethod,
final MultiMap<PsiElement, String> conflicts,
final List<MethodSignature> prototypeSignatures) {
final boolean isStatic = prototype.hasModifierProperty(PsiModifier.STATIC);
final String name = prototype.getName();
if (!GroovyPropertyUtils.isProperty(clazz, name, isStatic)) return;
@@ -74,20 +75,26 @@ public class GrMethodConflictUtil {
}
if (!(returnType instanceof GrClosureType)) return;
final GrClosureSignature signature = ((GrClosureType)returnType).getSignature();
NextSignature:
for (MethodSignature prototypeSignature : prototypeSignatures) {
final GrClosureParameter[] params = signature.getParameters();
final PsiType[] types = prototypeSignature.getParameterTypes();
if (types.length != params.length) continue;
for (int i = 0; i < types.length; i++) {
if (!TypesUtil.isAssignableByMethodCallConversion(types[i], params[i].getType(), refactoredMethod.getParameterList())) {
continue NextSignature;
final GrSignature signature = ((GrClosureType)returnType).getSignature();
signature.accept(new GrRecursiveSignatureVisitor() {
@Override
public void visitClosureSignature(GrClosureSignature signature) {
NextSignature:
for (MethodSignature prototypeSignature : prototypeSignatures) {
final GrClosureParameter[] params = signature.getParameters();
final PsiType[] types = prototypeSignature.getParameterTypes();
if (types.length != params.length) continue;
for (int i = 0; i < types.length; i++) {
if (!TypesUtil.isAssignableByMethodCallConversion(types[i], params[i].getType(), refactoredMethod.getParameterList())) {
continue NextSignature;
}
}
conflicts.putValue(getter, GroovyRefactoringBundle.message("refactored.method.will.cover.closure.property", name, RefactoringUIUtil.getDescription(getter.getContainingClass(), false)));
}
}
conflicts.putValue(getter, GroovyRefactoringBundle.message("refactored.method.will.cover.closure.property", name, RefactoringUIUtil.getDescription(getter.getContainingClass(), false)));
}
});
}
private static void checkForMethodSignatureOverload(PsiClass clazz,
@@ -121,13 +128,13 @@ public class GrMethodConflictUtil {
if (GroovyPropertyUtils.isSimplePropertySetter(prototype)) {
String propertyName = GroovyPropertyUtils.getPropertyNameBySetter(prototype);
PsiMethod setter =
GroovyPropertyUtils.findPropertySetter(clazz, propertyName, prototype.hasModifierProperty(GrModifier.STATIC), false);
GroovyPropertyUtils.findPropertySetter(clazz, propertyName, prototype.hasModifierProperty(PsiModifier.STATIC), false);
if (setter instanceof GrAccessorMethod) {
conflicts.putValue(setter, GroovyRefactoringBundle.message("replace.setter.for.property", propertyName));
}
}
else if (GroovyPropertyUtils.isSimplePropertyGetter(prototype)) {
boolean isStatic = prototype.hasModifierProperty(GrModifier.STATIC);
boolean isStatic = prototype.hasModifierProperty(PsiModifier.STATIC);
String propertyName = GroovyPropertyUtils.getPropertyNameByGetter(prototype);
PsiMethod getter = GroovyPropertyUtils.findPropertyGetter(clazz, propertyName, isStatic, false);
if (getter instanceof GrAccessorMethod) {
@@ -18,22 +18,22 @@ package org.jetbrains.plugins.groovy.refactoring.convertToJava;
import com.intellij.psi.*;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.ModifierListGenerator.JAVA_MODIFIERS_WITHOUT_ABSTRACT;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil.writeType;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.ModifierListGenerator.JAVA_MODIFIERS_WITHOUT_ABSTRACT;
/**
* @author Maxim.Medvedev
@@ -24,13 +24,13 @@ import com.intellij.psi.PsiType;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
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.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import java.util.Arrays;
@@ -30,6 +30,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
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.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrDefaultAnnotationValue;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
@@ -41,9 +42,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConstantInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import java.util.*;
@@ -49,8 +49,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Collection;
@@ -32,6 +32,7 @@ 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.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
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.GrVariableDeclaration;
@@ -48,7 +49,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrM
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrArrayTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
@@ -58,9 +58,9 @@ import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrLiteralClassType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.ClosureSyntheticParameter;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
@@ -23,6 +23,7 @@ import com.intellij.util.containers.HashMap;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -30,10 +31,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.Map;
@@ -49,6 +49,7 @@ import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -59,11 +60,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
@@ -55,8 +56,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisRe
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@@ -51,8 +52,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrM
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil;
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -38,8 +39,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -888,4 +888,40 @@ Date d = <warning descr="Cannot assign 'Object' to 'Date'">a.cl()</warning>
myFixture.enableInspections(inspections)
myFixture.testHighlighting(true, false, true)
}
void testMethodRefs1() {
myFixture.configureByText('_.groovy', '''\
class A {
int foo(){2}
Date foo(int x) {null}
}
def foo = new A().&foo
int i = foo()
int i2 = <warning descr="Cannot assign 'Date' to 'int'">foo(2)</warning>
Date d = foo(2)
Date d2 = <warning descr="Cannot assign 'Integer' to 'Date'">foo()</warning>
''')
testHighlighting(GroovyAssignabilityCheckInspection)
}
void testMethodRefs2() {
myFixture.configureByText('_.groovy', '''\
class Bar {
def foo(int i, String s2) {s2}
def foo(int i, int i2) {i2}
}
def cl = new Bar<error descr="'(' expected">.</error>&foo
cl = cl.curry(1)
String s = cl("2")
int s2 = <warning descr="Cannot assign 'String' to 'int'">cl("2")</warning>
int i = cl(3)
String i2 = cl(3)
''')
testHighlighting(GroovyAssignabilityCheckInspection)
}
}
@@ -1,2 +1,2 @@
groovy.lang.Closure a = new org.codehaus.groovy.runtime.MethodClosure(new java.util.ArrayList<java.lang.String>(), "add");
groovy.lang.Closure<java.lang.Object> a = new org.codehaus.groovy.runtime.MethodClosure(new java.util.ArrayList<java.lang.String>(), "add");
a.call("2");