mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
recognize OMI when instatiating objects as list literals
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
<orderEntry type="module" module-name="lang-api" />
|
||||
<orderEntry type="module" module-name="idea-ui" />
|
||||
<orderEntry type="module" module-name="openapi" />
|
||||
<orderEntry type="module" module-name="java-impl" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
<name>Groovy++ Support</name>
|
||||
<description>Adds code assistance for the Groovy++ features</description>
|
||||
<version>0.1</version>
|
||||
<idea-version since-build="95.90" until-build="96.1"/>
|
||||
<idea-version since-build="95.90" until-build="96.239"/>
|
||||
<vendor logo="/org/jetbrains/plugins/groovy/images/groovy_16x16.png" url="http://www.jetbrains.com">JetBrains Inc.</vendor>
|
||||
<depends>org.intellij.groovy</depends>
|
||||
|
||||
<extensions defaultExtensionNs="org.intellij.groovy">
|
||||
<libraryManager implementation="org.jetbrains.plugins.groovy.gpp.GppLibraryManager" order="first"/>
|
||||
<typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
|
||||
<expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
|
||||
<variableEnhancer implementation="org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider"/>
|
||||
</extensions>
|
||||
|
||||
|
||||
+34
-11
@@ -10,13 +10,14 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.AbstractClosureParameterEnhancer;
|
||||
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.statements.arguments.GrArgumentLabel;
|
||||
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.expectedTypes.GroovyExpectedTypesProvider;
|
||||
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 java.util.*;
|
||||
@@ -40,7 +41,37 @@ public class GppClosureParameterTypeProvider extends AbstractClosureParameterEnh
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PsiType constraint : getExpectedTypes(closure)) {
|
||||
final PsiElement parent = closure.getParent();
|
||||
if (parent instanceof GrListOrMap) {
|
||||
final GrListOrMap list = (GrListOrMap)parent;
|
||||
if (!list.isMap()) {
|
||||
final PsiType listType = list.getType();
|
||||
final int argIndex = Arrays.asList(list.getInitializers()).indexOf(closure);
|
||||
assert argIndex >= 0;
|
||||
if (listType instanceof GrTupleType) {
|
||||
for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(list)) {
|
||||
if (type instanceof PsiClassType) {
|
||||
for (GroovyResolveResult resolveResult : GppTypeConverter
|
||||
.getConstructorCandidates((PsiClassType)type, ((GrTupleType)listType).getComponentTypes(), closure)) {
|
||||
final PsiElement method = resolveResult.getElement();
|
||||
if (method instanceof PsiMethod && ((PsiMethod)method).isConstructor()) {
|
||||
final PsiType toCastTo =
|
||||
resolveResult.getSubstitutor().substitute(((PsiMethod)method).getParameterList().getParameters()[argIndex].getType());
|
||||
final PsiType suggestion = getSingleMethodParameterType(toCastTo, index, closure);
|
||||
if (suggestion != null) {
|
||||
return suggestion;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiType constraint : GroovyExpectedTypesProvider.getDefaultExpectedTypes(closure)) {
|
||||
final PsiType suggestion = getSingleMethodParameterType(constraint, index, closure);
|
||||
if (suggestion != null) {
|
||||
return suggestion;
|
||||
@@ -49,14 +80,6 @@ public class GppClosureParameterTypeProvider extends AbstractClosureParameterEnh
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Set<PsiType> getExpectedTypes(GrExpression element) {
|
||||
final LinkedHashSet<PsiType> result = new LinkedHashSet<PsiType>();
|
||||
for (TypeConstraint constraint : GroovyExpectedTypesProvider.calculateTypeConstraints(element)) {
|
||||
result.add(constraint.getDefaultType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiMethod, PsiSubstitutor> getOverriddenMethod(GrClosableBlock closure) {
|
||||
final PsiElement parent = closure.getParent();
|
||||
@@ -76,7 +99,7 @@ public class GppClosureParameterTypeProvider extends AbstractClosureParameterEnh
|
||||
|
||||
final PsiElement map = parent.getParent();
|
||||
if (map instanceof GrListOrMap && ((GrListOrMap)map).isMap()) {
|
||||
for (PsiType expected : getExpectedTypes((GrExpression)map)) {
|
||||
for (PsiType expected : GroovyExpectedTypesProvider.getDefaultExpectedTypes((GrExpression)map)) {
|
||||
if (expected instanceof PsiClassType) {
|
||||
final List<Pair<PsiMethod, PsiSubstitutor>> pairs = getMethodsToOverrideImplementInInheritor((PsiClassType)expected, false);
|
||||
final List<Pair<PsiMethod, PsiSubstitutor>> withName =
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package org.jetbrains.plugins.groovy.gpp;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class GppExpectedTypesContributor extends GroovyExpectedTypesContributor {
|
||||
@Override
|
||||
public List<TypeConstraint> calculateTypeConstraints(@NotNull GrExpression expression) {
|
||||
if (!GppTypeConverter.hasTypedContext(expression)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final PsiElement parent = expression.getParent();
|
||||
if (parent instanceof GrListOrMap) {
|
||||
final GrListOrMap list = (GrListOrMap)parent;
|
||||
if (!list.isMap()) {
|
||||
return addExpectedConstructorParameters(expression, list);
|
||||
}
|
||||
else {
|
||||
//todo expected property types
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static List<TypeConstraint> addExpectedConstructorParameters(GrExpression expression, GrListOrMap list) {
|
||||
final PsiType listType = list.getType();
|
||||
if (!(listType instanceof GrTupleType)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final PsiType[] argTypes = ((GrTupleType)listType).getComponentTypes();
|
||||
final int argIndex = Arrays.asList(list.getInitializers()).indexOf(expression);
|
||||
assert argIndex >= 0;
|
||||
|
||||
final ArrayList<TypeConstraint> result = new ArrayList<TypeConstraint>();
|
||||
for (PsiType type : GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression)) {
|
||||
if (type instanceof PsiClassType) {
|
||||
for (GroovyResolveResult resolveResult : GppTypeConverter.getConstructorCandidates((PsiClassType)type, argTypes, expression)) {
|
||||
final PsiElement method = resolveResult.getElement();
|
||||
if (method instanceof PsiMethod && ((PsiMethod)method).isConstructor()) {
|
||||
final PsiParameter[] constructorParameters = ((PsiMethod)method).getParameterList().getParameters();
|
||||
if (constructorParameters.length > argIndex) {
|
||||
final PsiType toCastTo = resolveResult.getSubstitutor().substitute(constructorParameters[argIndex].getType());
|
||||
result.add(SubtypeConstraint.create(toCastTo));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -105,19 +105,21 @@ public class GppTypeConverter extends GrTypeConverter {
|
||||
}
|
||||
|
||||
private static boolean hasConstructor(PsiClassType lType, PsiType[] argTypes, GroovyPsiElement context) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = lType.resolveGenerics();
|
||||
return getConstructorCandidates(lType, argTypes, context).length == 1;
|
||||
}
|
||||
|
||||
public static GroovyResolveResult[] getConstructorCandidates(PsiClassType classType, PsiType[] argTypes, GroovyPsiElement context) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (psiClass == null) {
|
||||
return false;
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
final GroovyResolveResult grResult = resolveResult instanceof GroovyResolveResult
|
||||
? (GroovyResolveResult)resolveResult
|
||||
: new GroovyResolveResultImpl(psiClass, context, substitutor, true, true);
|
||||
final GroovyResolveResult[] candidates = org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getConstructorCandidates(
|
||||
context, new GroovyResolveResult[]{grResult}, argTypes);
|
||||
return candidates.length == 1;
|
||||
return org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.getConstructorCandidates(context, new GroovyResolveResult[]{grResult}, argTypes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<extensionPoint name="nonCodeProcessor" interface="org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersProcessor"/>
|
||||
<extensionPoint name="variableEnhancer" interface="org.jetbrains.plugins.groovy.lang.psi.GrVariableEnhancer"/>
|
||||
<extensionPoint name="typeConverter" interface="org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter"/>
|
||||
<extensionPoint name="expectedTypesContributor" interface="org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesContributor"/>
|
||||
|
||||
<extensionPoint name="positionManagerDelegate" interface="org.jetbrains.plugins.groovy.extensions.debugger.ScriptPositionManagerHelper"/>
|
||||
<extensionPoint name="compilerExtension" interface="org.jetbrains.plugins.groovy.compiler.GroovyCompilerExtension"/>
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class GroovyExpectedTypesContributor {
|
||||
public static final ExtensionPointName<GroovyExpectedTypesContributor> EP_NAME = ExtensionPointName.create("org.intellij.groovy.expectedTypesContributor");
|
||||
|
||||
public abstract List<TypeConstraint> calculateTypeConstraints(@NotNull GrExpression expression);
|
||||
}
|
||||
+22
-4
@@ -38,9 +38,7 @@ 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.resolve.ResolveUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
@@ -52,7 +50,27 @@ public class GroovyExpectedTypesProvider {
|
||||
public static TypeConstraint[] calculateTypeConstraints(GrExpression expression) {
|
||||
MyCalculator calculator = new MyCalculator(expression);
|
||||
((GroovyPsiElement)expression.getParent()).accept(calculator);
|
||||
return calculator.getResult();
|
||||
final TypeConstraint[] result = calculator.getResult();
|
||||
|
||||
List<TypeConstraint> custom = new ArrayList<TypeConstraint>();
|
||||
for (GroovyExpectedTypesContributor contributor : GroovyExpectedTypesContributor.EP_NAME.getExtensions()) {
|
||||
custom.addAll(contributor.calculateTypeConstraints(expression));
|
||||
}
|
||||
|
||||
if (!custom.isEmpty()) {
|
||||
custom.addAll(0, Arrays.asList(result));
|
||||
return custom.toArray(new TypeConstraint[custom.size()]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Set<PsiType> getDefaultExpectedTypes(GrExpression element) {
|
||||
final LinkedHashSet<PsiType> result = new LinkedHashSet<PsiType>();
|
||||
for (TypeConstraint constraint : calculateTypeConstraints(element)) {
|
||||
result.add(constraint.getDefaultType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -235,6 +235,20 @@ class Foo<T> {
|
||||
@Typed Foo<String> bar() {
|
||||
return [foo: { it.subs<caret> }]
|
||||
}
|
||||
"""
|
||||
myFixture.completeBasic()
|
||||
assertSameElements myFixture.lookupElementStrings, "subSequence", "substring", "substring"
|
||||
}
|
||||
|
||||
public void testClosureInListInstantiation() throws Exception {
|
||||
myFixture.configureByText "a.groovy", """
|
||||
class Foo {
|
||||
def Foo(int a, Function1<String, Integer> f) {}
|
||||
}
|
||||
|
||||
@Typed Foo foo() {
|
||||
[239, { s -> s.subs<caret> }]
|
||||
}
|
||||
"""
|
||||
myFixture.completeBasic()
|
||||
assertSameElements myFixture.lookupElementStrings, "subSequence", "substring", "substring"
|
||||
|
||||
Reference in New Issue
Block a user