IDEA-123337 lazy type inference for map literals

This commit is contained in:
Max Medvedev
2014-04-08 17:45:54 +04:00
parent 6e96d422a8
commit 21c1cbff05
9 changed files with 378 additions and 145 deletions
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -46,10 +47,16 @@ public abstract class GrLiteralClassType extends PsiClassType {
@Override
@NotNull
public ClassResolveResult resolveGenerics() {
final PsiClass myBaseClass = resolve();
final PsiSubstitutor substitutor = inferSubstitutor(myBaseClass);
return new ClassResolveResult() {
private final PsiClass myBaseClass = resolve();
private final NotNullLazyValue<PsiSubstitutor> mySubstitutor = new NotNullLazyValue<PsiSubstitutor>() {
@NotNull
@Override
protected PsiSubstitutor compute() {
return inferSubstitutor(myBaseClass);
}
};
@Override
public PsiClass getElement() {
@@ -59,7 +66,7 @@ public abstract class GrLiteralClassType extends PsiClassType {
@Override
@NotNull
public PsiSubstitutor getSubstitutor() {
return substitutor;
return mySubstitutor.getValue();
}
@Override
@@ -167,7 +174,7 @@ public abstract class GrLiteralClassType extends PsiClassType {
@Override
public boolean equalsToText(@NotNull @NonNls String text) {
return text != null && text.equals(getJavaClassName());
return text.equals(getJavaClassName());
}
@Override
@@ -16,17 +16,19 @@
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import java.util.*;
@@ -36,49 +38,33 @@ import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.
/**
* @author peter
*/
public class GrMapType extends GrLiteralClassType {
private final Map<String, PsiType> myStringEntries;
private final List<Pair<PsiType, PsiType>> myOtherEntries;
public abstract class GrMapType extends GrLiteralClassType {
private final String myJavaClassName;
private GrMapType(JavaPsiFacade facade,
GlobalSearchScope scope,
Map<String, PsiType> stringEntries,
List<Pair<PsiType, PsiType>> otherEntries,
LanguageLevel languageLevel) {
super(languageLevel, scope, facade);
myStringEntries = stringEntries;
myOtherEntries = otherEntries;
private final AtomicNotNullLazyValue<PsiType[]> myParameters = new AtomicNotNullLazyValue<PsiType[]>() {
@NotNull
@Override
protected PsiType[] compute() {
final PsiType[] keyTypes = getAllKeyTypes();
final PsiType[] valueTypes = getAllValueTypes();
if (keyTypes.length == 0 && valueTypes.length == 0) {
return EMPTY_ARRAY;
}
myJavaClassName = facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : JAVA_UTIL_MAP;
return new PsiType[]{getLeastUpperBound(keyTypes), getLeastUpperBound(valueTypes)};
}
};
protected GrMapType(JavaPsiFacade facade, GlobalSearchScope scope) {
this(facade, scope, LanguageLevel.JDK_1_5);
}
public GrMapType(@NotNull PsiElement context, GrNamedArgument[] args) {
super(LanguageLevel.JDK_1_5, context.getResolveScope(), JavaPsiFacade.getInstance(context.getProject()));
protected GrMapType(JavaPsiFacade facade,
GlobalSearchScope scope,
LanguageLevel languageLevel) {
super(languageLevel, scope, facade);
myJavaClassName = myFacade.findClass(JAVA_UTIL_LINKED_HASH_MAP, myScope) != null ? JAVA_UTIL_LINKED_HASH_MAP : JAVA_UTIL_MAP;
myStringEntries = new HashMap<String, PsiType>();
myOtherEntries = new ArrayList<Pair<PsiType, PsiType>>();
for (GrNamedArgument arg : args) {
GrArgumentLabel label = arg.getLabel();
if (label == null) continue;
GrExpression expression = arg.getExpression();
if (expression == null || expression.getType() == null) continue;
String labelName = label.getName();
GrExpression labelExpression = label.getExpression();
if (labelName != null) {
myStringEntries.put(labelName, expression.getType());
}
else if (labelExpression != null) {
PsiType type = labelExpression.getType();
myOtherEntries.add(new Pair<PsiType, PsiType>(type, expression.getType()));
}
}
myJavaClassName = facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : JAVA_UTIL_MAP;
}
@NotNull
@@ -94,63 +80,49 @@ public class GrMapType extends GrLiteralClassType {
}
@Nullable
public PsiType getTypeByStringKey(String key) {
return myStringEntries.get(key);
}
public abstract PsiType getTypeByStringKey(String key);
public Set<String> getStringKeys() {
return myStringEntries.keySet();
}
@NotNull
public abstract Set<String> getStringKeys();
public PsiType[] getAllKeyTypes() {
Set<PsiType> result = new HashSet<PsiType>();
if (!myStringEntries.isEmpty()) {
result.add(GroovyPsiManager.getInstance(myFacade.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, getResolveScope()));
}
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
result.add(entry.first);
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
public abstract boolean isEmpty();
public PsiType[] getAllValueTypes() {
Set<PsiType> result = new HashSet<PsiType>();
result.addAll(myStringEntries.values());
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
result.add(entry.second);
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
@NotNull
protected abstract PsiType[] getAllKeyTypes();
@NotNull
protected abstract PsiType[] getAllValueTypes();
@NotNull
protected abstract List<Pair<PsiType, PsiType>> getOtherEntries();
@NotNull
protected abstract Map<String, PsiType> getStringEntries();
@Override
@NotNull
public PsiType[] getParameters() {
final PsiType[] keyTypes = getAllKeyTypes();
final PsiType[] valueTypes = getAllValueTypes();
if (keyTypes.length == 0 && valueTypes.length == 0) {
return EMPTY_ARRAY;
}
return new PsiType[]{getLeastUpperBound(keyTypes), getLeastUpperBound(valueTypes)};
return myParameters.getValue();
}
@Override
@NotNull
public String getInternalCanonicalText() {
if (myStringEntries.isEmpty()) {
if (myOtherEntries.isEmpty()) return "[:]";
Set<String> stringKeys = getStringKeys();
List<Pair<PsiType, PsiType>> otherEntries = getOtherEntries();
if (stringKeys.isEmpty()) {
if (otherEntries.isEmpty()) return "[:]";
String name = getJavaClassName();
final PsiType[] params = getParameters();
return name + "<" + getInternalText(params[0]) + ", " + getInternalText(params[1]) + ">";
}
List<String> components = new ArrayList<String>();
for (String s : myStringEntries.keySet()) {
components.add("'" + s + "':" + getInternalCanonicalText(myStringEntries.get(s)));
for (String s : stringKeys) {
components.add("'" + s + "':" + getInternalCanonicalText(getTypeByStringKey(s)));
}
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
for (Pair<PsiType, PsiType> entry : otherEntries) {
components.add(getInternalCanonicalText(entry.first) + ":" + getInternalCanonicalText(entry.second));
}
boolean tooMany = components.size() > 2;
@@ -163,34 +135,11 @@ public class GrMapType extends GrLiteralClassType {
return param == null ? "null" : param.getInternalCanonicalText();
}
@Override
public boolean isValid() {
for (PsiType type : myStringEntries.values()) {
if (type != null && !type.isValid()) {
return false;
}
}
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
if (entry.first != null && !entry.first.isValid()) {
return false;
}
if (entry.second != null && !entry.second.isValid()) {
return false;
}
}
return true;
}
@Override
@NotNull
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
return new GrMapType(myFacade, getResolveScope(), myStringEntries, myOtherEntries, languageLevel);
}
public boolean equals(Object obj) {
if (obj instanceof GrMapType) {
return myStringEntries.equals(((GrMapType)obj).myStringEntries) && myOtherEntries.equals(((GrMapType)obj).myOtherEntries);
GrMapType other = (GrMapType)obj;
return getStringEntries().equals(other.getStringEntries()) &&
getOtherEntries().equals(other.getOtherEntries());
}
return super.equals(obj);
}
@@ -204,12 +153,12 @@ public class GrMapType extends GrLiteralClassType {
final GlobalSearchScope scope = l.getScope().intersectWith(r.getResolveScope());
final Map<String, PsiType> strings = new HashMap<String, PsiType>();
strings.putAll(l.myStringEntries);
strings.putAll(r.myStringEntries);
strings.putAll(l.getStringEntries());
strings.putAll(r.getStringEntries());
List<Pair<PsiType, PsiType>> other = new ArrayList<Pair<PsiType, PsiType>>();
other.addAll(l.myOtherEntries);
other.addAll(r.myOtherEntries);
other.addAll(l.getOtherEntries());
other.addAll(r.getOtherEntries());
return create(l.myFacade, scope, strings, other);
}
@@ -218,13 +167,23 @@ public class GrMapType extends GrLiteralClassType {
GlobalSearchScope scope,
Map<String, PsiType> stringEntries,
List<Pair<PsiType, PsiType>> otherEntries) {
return new GrMapType(facade, scope, stringEntries, otherEntries, LanguageLevel.JDK_1_5);
return new GrMapTypeImpl(facade, scope, stringEntries, otherEntries, LanguageLevel.JDK_1_5);
}
public static GrMapType create(GlobalSearchScope scope) {
JavaPsiFacade facade = JavaPsiFacade.getInstance(scope.getProject());
List<Pair<PsiType, PsiType>> otherEntries = Collections.emptyList();
Map<String, PsiType> stringEntries = Collections.emptyMap();
return new GrMapType(facade, scope, stringEntries, otherEntries, LanguageLevel.JDK_1_5);
return new GrMapTypeImpl(facade, scope, stringEntries, otherEntries, LanguageLevel.JDK_1_5);
}
@NotNull
@Override
public PsiClassType setLanguageLevel(@NotNull LanguageLevel languageLevel) {
return new GrMapTypeImpl(myFacade, getResolveScope(), getStringEntries(), getOtherEntries(), languageLevel);
}
public static GrMapType createFromNamedArgs(PsiElement context, GrNamedArgument[] args) {
return new GrMapTypeFromNamedArgs(context, args);
}
}
@@ -0,0 +1,169 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by Max Medvedev on 07/04/14
*/
public class GrMapTypeFromNamedArgs extends GrMapType {
private final Map<String, GrExpression> myStringEntries;
private final List<Pair<GrExpression, GrExpression>> myOtherEntries;
private final AtomicNotNullLazyValue<List<Pair<PsiType, PsiType>>> myTypesOfOtherEntries = new AtomicNotNullLazyValue<List<Pair<PsiType, PsiType>>>() {
@NotNull
@Override
protected List<Pair<PsiType, PsiType>> compute() {
return ContainerUtil.map(myOtherEntries, new Function<Pair<GrExpression, GrExpression>, Pair<PsiType, PsiType>>() {
@Override
public Pair<PsiType, PsiType> fun(Pair<GrExpression, GrExpression> pair) {
return Pair.create(pair.first.getType(), pair.second.getType());
}
});
}
};
private final AtomicNotNullLazyValue<Map<String, PsiType>> myTypesOfStringEntries = new AtomicNotNullLazyValue<Map<String, PsiType>>() {
@NotNull
@Override
protected Map<String, PsiType> compute() {
HashMap<String, PsiType> result = ContainerUtil.newHashMap();
for (Map.Entry<String, GrExpression> entry : myStringEntries.entrySet()) {
result.put(entry.getKey(), entry.getValue().getType());
}
return result;
}
};
public GrMapTypeFromNamedArgs(@NotNull PsiElement context, @NotNull GrNamedArgument[] namedArgs) {
this(JavaPsiFacade.getInstance(context.getProject()), context.getResolveScope(), namedArgs);
}
public GrMapTypeFromNamedArgs(@NotNull JavaPsiFacade facade, @NotNull GlobalSearchScope scope, @NotNull GrNamedArgument[] namedArgs) {
super(facade, scope);
myStringEntries = ContainerUtil.newHashMap();
myOtherEntries = ContainerUtil.newArrayList();
for (GrNamedArgument namedArg : namedArgs) {
final GrArgumentLabel label = namedArg.getLabel();
final GrExpression expression = namedArg.getExpression();
if (label == null || expression == null) {
continue;
}
final String name = label.getName();
if (name != null) {
myStringEntries.put(name, expression);
}
else if (label.getExpression() != null) {
myOtherEntries.add(Pair.create(label.getExpression(), expression));
}
}
}
@Nullable
@Override
public PsiType getTypeByStringKey(String key) {
GrExpression expression = myStringEntries.get(key);
return expression != null ? expression.getType() : null;
}
@NotNull
@Override
public Set<String> getStringKeys() {
return myStringEntries.keySet();
}
@Override
public boolean isEmpty() {
return myStringEntries.isEmpty() && myOtherEntries.isEmpty();
}
@NotNull
@Override
protected PsiType[] getAllKeyTypes() {
Set<PsiType> result = ContainerUtil.newHashSet();
if (!myStringEntries.isEmpty()) {
result.add(GroovyPsiManager.getInstance(myFacade.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, getResolveScope()));
}
for (Pair<GrExpression, GrExpression> entry : myOtherEntries) {
result.add(entry.first.getType());
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
@NotNull
@Override
protected PsiType[] getAllValueTypes() {
Set<PsiType> result = ContainerUtil.newHashSet();
for (GrExpression expression : myStringEntries.values()) {
result.add(expression.getType());
}
for (Pair<GrExpression, GrExpression> entry : myOtherEntries) {
result.add(entry.second.getType());
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
@NotNull
@Override
protected List<Pair<PsiType, PsiType>> getOtherEntries() {
return myTypesOfOtherEntries.getValue();
}
@NotNull
@Override
protected Map<String, PsiType> getStringEntries() {
return myTypesOfStringEntries.getValue();
}
@Override
public boolean isValid() {
for (GrExpression expression : myStringEntries.values()) {
if (!expression.isValid()) return false;
}
for (Pair<GrExpression, GrExpression> entry : myOtherEntries) {
if (!entry.first.isValid()) return false;
if (!entry.second.isValid()) return false;
}
return true;
}
}
@@ -0,0 +1,118 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by Max Medvedev on 07/04/14
*/
public class GrMapTypeImpl extends GrMapType {
private final Map<String, PsiType> myStringEntries;
private final List<Pair<PsiType, PsiType>> myOtherEntries;
GrMapTypeImpl(JavaPsiFacade facade,
GlobalSearchScope scope,
Map<String, PsiType> stringEntries,
List<Pair<PsiType, PsiType>> otherEntries,
LanguageLevel languageLevel) {
super(facade, scope, languageLevel);
myStringEntries = stringEntries;
myOtherEntries = otherEntries;
}
@Nullable
public PsiType getTypeByStringKey(String key) {
return myStringEntries.get(key);
}
@NotNull
public Set<String> getStringKeys() {
return myStringEntries.keySet();
}
@NotNull
protected PsiType[] getAllKeyTypes() {
Set<PsiType> result = new HashSet<PsiType>();
if (!myStringEntries.isEmpty()) {
result.add(GroovyPsiManager.getInstance(myFacade.getProject()).createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, getResolveScope()));
}
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
result.add(entry.first);
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
@NotNull
protected PsiType[] getAllValueTypes() {
Set<PsiType> result = new HashSet<PsiType>();
result.addAll(myStringEntries.values());
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
result.add(entry.second);
}
result.remove(null);
return result.toArray(createArray(result.size()));
}
@NotNull
@Override
protected List<Pair<PsiType, PsiType>> getOtherEntries() {
return myOtherEntries;
}
@NotNull
@Override
protected Map<String, PsiType> getStringEntries() {
return myStringEntries;
}
@Override
public boolean isValid() {
for (PsiType type : myStringEntries.values()) {
if (type != null && !type.isValid()) {
return false;
}
}
for (Pair<PsiType, PsiType> entry : myOtherEntries) {
if (entry.first != null && !entry.first.isValid()) {
return false;
}
if (entry.second != null && !entry.second.isValid()) {
return false;
}
}
return true;
}
@Override
public boolean isEmpty() {
return myStringEntries.isEmpty() && myOtherEntries.isEmpty();
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.search.GlobalSearchScope;
@@ -36,7 +35,6 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
@@ -50,7 +48,6 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMMA;
@@ -191,10 +188,8 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap {
@Override
@Nullable
public PsiType fun(GrListOrMapImpl listOrMap) {
final GlobalSearchScope scope = listOrMap.getResolveScope();
if (listOrMap.isMap()) {
JavaPsiFacade facade = JavaPsiFacade.getInstance(listOrMap.getProject());
return inferMapInitializerType(listOrMap, facade, scope);
return inferMapInitializerType(listOrMap);
}
PsiElement parent = listOrMap.getParent();
@@ -210,15 +205,15 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap {
}
@Nullable
private static PsiClassType inferMapInitializerType(GrListOrMapImpl listOrMap, JavaPsiFacade facade, GlobalSearchScope scope) {
final HashMap<String, PsiType> stringEntries = new HashMap<String, PsiType>();
final ArrayList<Pair<PsiType, PsiType>> otherEntries = new ArrayList<Pair<PsiType, PsiType>>();
private static PsiClassType inferMapInitializerType(GrListOrMapImpl listOrMap) {
GrNamedArgument[] namedArgs = listOrMap.getNamedArguments();
if (namedArgs.length == 0) {
PsiType lType = PsiImplUtil.inferExpectedTypeForDiamond(listOrMap);
if (lType instanceof PsiClassType && InheritanceUtil.isInheritor(lType, CommonClassNames.JAVA_UTIL_MAP)) {
GlobalSearchScope scope = listOrMap.getResolveScope();
JavaPsiFacade facade = JavaPsiFacade.getInstance(listOrMap.getProject());
PsiClass hashMap = facade.findClass(GroovyCommonClassNames.JAVA_UTIL_LINKED_HASH_MAP, scope);
if (hashMap == null) hashMap = facade.findClass(CommonClassNames.JAVA_UTIL_MAP, scope);
if (hashMap != null) {
@@ -230,22 +225,7 @@ public class GrListOrMapImpl extends GrExpressionImpl implements GrListOrMap {
}
}
for (GrNamedArgument namedArg : namedArgs) {
final GrArgumentLabel label = namedArg.getLabel();
final GrExpression expression = namedArg.getExpression();
if (label == null || expression == null) {
continue;
}
final String name = label.getName();
if (name != null) {
stringEntries.put(name, expression.getType());
} else {
otherEntries.add(Pair.create(label.getLabelType(), expression.getType()));
}
}
return GrMapType.create(facade, scope, stringEntries, otherEntries);
return GrMapType.createFromNamedArgs(listOrMap, namedArgs);
}
@@ -873,7 +873,7 @@ public class GrClosureSignatureUtil {
for (int i = 0, size = arg.args.size(); i < size; i++) {
args[i] = (GrNamedArgument)arg.args.get(i);
}
return new GrMapType(first, args);
return GrMapType.createFromNamedArgs(first, args);
}
else {
for (PsiElement elem : arg.args) {
@@ -244,7 +244,7 @@ public class GrNewExpressionImpl extends GrCallExpressionImpl implements GrNewEx
if (argumentList == null) return GroovyResolveResult.EMPTY_ARRAY;
if (argumentList.getNamedArguments().length > 0 && argumentList.getExpressionArguments().length == 0) {
PsiType mapType = new GrMapType(argumentList, getNamedArguments());
PsiType mapType = GrMapType.createFromNamedArgs(argumentList, getNamedArguments());
GroovyResolveResult[] constructorResults = PsiUtil.getConstructorCandidates(ref, classCandidate, new PsiType[]{mapType}); //one Map parameter, actually
for (GroovyResolveResult result : constructorResults) {
final PsiElement resolved = result.getElement();
@@ -583,8 +583,7 @@ public class TypesUtil {
private static boolean checkEmptyMapAndMap(PsiType type1, PsiType type2) {
if (type1 instanceof GrMapType) {
PsiType[] types = ((GrMapType)type1).getAllKeyTypes();
if (types.length == 0 && InheritanceUtil.isInheritor(type2, JAVA_UTIL_MAP)) return true;
if (((GrMapType)type1).isEmpty() && InheritanceUtil.isInheritor(type2, JAVA_UTIL_MAP)) return true;
}
return false;
@@ -308,7 +308,8 @@ public class PsiUtil {
List<PsiType> result = new ArrayList<PsiType>();
if (namedArgs.length > 0) {
result.add(new GrMapType(namedArgs[0], byShape ? new GrNamedArgument[0] : namedArgs));
GrNamedArgument context = namedArgs[0];
result.add(GrMapType.createFromNamedArgs(context, byShape ? new GrNamedArgument[0] : namedArgs));
}
for (GrExpression expression : expressions) {