2 * Copyright 2000-2010 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.plugins.groovy.lang.psi.impl.types;
18 import com.intellij.openapi.util.Comparing;
19 import com.intellij.psi.*;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
22 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
23 import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature;
24 import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
25 import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
28 * @author Maxim.Medvedev
30 public class GrClosureSignatureImpl implements GrClosureSignature {
31 private final boolean myIsVarargs;
32 @Nullable private final PsiType myReturnType;
33 @NotNull private final GrClosureParameter[] myParameters;
34 @NotNull private PsiSubstitutor mySubstitutor;
36 public GrClosureSignatureImpl(@NotNull PsiParameter[] parameters, @Nullable PsiType returnType, @NotNull PsiSubstitutor substitutor) {
37 myReturnType = substitutor.substitute(returnType);
38 final int length = parameters.length;
39 myParameters = new GrClosureParameter[length];
40 for (int i = 0; i < length; i++) {
41 myParameters[i] = new GrClosureParameterImpl(parameters[i], substitutor);
44 myIsVarargs = /*parameters[length - 1].isVarArgs() ||*/ myParameters[length - 1].getType() instanceof PsiArrayType;
49 mySubstitutor = substitutor;
52 public GrClosureSignatureImpl(PsiParameter[] parameters, PsiType returnType) {
53 this(parameters, returnType, PsiSubstitutor.EMPTY);
56 GrClosureSignatureImpl(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs) {
57 myParameters = params;
58 myReturnType = returnType;
59 myIsVarargs = isVarArgs;
63 public boolean isVarargs() {
69 public PsiType getReturnType() {
74 public PsiSubstitutor getSubstitutor() {
79 public GrClosureParameter[] getParameters() {
80 GrClosureParameter[] result = new GrClosureParameter[myParameters.length];
81 System.arraycopy(myParameters, 0, result, 0, myParameters.length);
86 public GrClosureSignature curry(int count) {
87 if (count > myParameters.length) {
89 return new DerivedClosureSignature();
95 GrClosureParameter[] newParams = new GrClosureParameter[myParameters.length - count];
96 System.arraycopy(myParameters, count, newParams, 0, newParams.length);
97 return new DerivedClosureSignature(newParams, null, myIsVarargs);
100 public boolean isValid() {
101 for (GrClosureParameter parameter : myParameters) {
102 if (!parameter.isValid()) return false;
104 final PsiType returnType = getReturnType();
105 return returnType == null || returnType.isValid();
109 public boolean equals(Object obj) {
110 if (obj instanceof GrClosureSignature) {
111 return Comparing.equal(myParameters, ((GrClosureSignature)obj).getParameters()) &&
112 Comparing.equal(myIsVarargs, ((GrClosureSignature)obj).isVarargs());
114 return super.equals(obj);
118 public static GrClosureSignature getLeastUpperBound(@NotNull GrClosureSignature signature1,
119 @NotNull GrClosureSignature signature2,
120 PsiManager manager) {
121 GrClosureParameter[] parameters1 = signature1.getParameters();
122 GrClosureParameter[] parameters2 = signature2.getParameters();
124 if (parameters1.length == parameters2.length) {
125 GrClosureParameter[] params = new GrClosureParameter[parameters1.length];
126 for (int i = 0; i < params.length; i++) {
127 final PsiType type = GenericsUtil.getGreatestLowerBound(parameters1[i].getType(), parameters2[i].getType());
128 boolean opt = parameters1[i].isOptional() && parameters2[i].isOptional();
129 params[i] = new GrClosureParameterImpl(type, opt, null);
131 final PsiType s1type = signature1.getReturnType();
132 final PsiType s2type = signature2.getReturnType();
133 PsiType returnType = null;
134 if (s1type != null && s2type != null) {
135 returnType = TypesUtil.getLeastUpperBound(s1type, s2type, manager);
137 boolean isVarArgs = signature1.isVarargs() && signature2.isVarargs();
138 return new GrClosureSignatureImpl(params, returnType, isVarArgs);
143 private class DerivedClosureSignature extends GrClosureSignatureImpl {
144 DerivedClosureSignature() {
145 super(PsiParameter.EMPTY_ARRAY, null);
148 DerivedClosureSignature(@NotNull GrClosureParameter[] params, @Nullable PsiType returnType, boolean isVarArgs) {
149 super(params, returnType, isVarArgs);
153 public PsiType getReturnType() {
154 return GrClosureSignatureImpl.this.getReturnType();