mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-118222 Closure to SAM interface coercion doesn't handle contravariant types correctly
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -55,6 +55,7 @@ public abstract class GroovyConfigUtils extends AbstractConfigUtils {
|
||||
public static final String GROOVY2_0 = "2.0";
|
||||
public static final String GROOVY2_1 = "2.1";
|
||||
public static final String GROOVY2_2 = "2.2";
|
||||
public static final String GROOVY2_3 = "2.3";
|
||||
|
||||
private static GroovyConfigUtils myGroovyConfigUtils;
|
||||
|
||||
|
||||
+11
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -15,9 +15,12 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
|
||||
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiWildcardType;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
|
||||
import org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression;
|
||||
@@ -63,7 +66,13 @@ public class ClosureAsAnonymousParameterEnhancer extends AbstractClosureParamete
|
||||
for (PsiType constraint : expectedTypes) {
|
||||
final PsiType suggestion = GppClosureParameterTypeProvider.getSingleMethodParameterType(constraint, index, closure);
|
||||
if (suggestion != null) {
|
||||
return suggestion;
|
||||
if (GroovyConfigUtils.getInstance().isVersionAtLeast(closure, GroovyConfigUtils.GROOVY2_3)) {
|
||||
if (suggestion instanceof PsiWildcardType && ((PsiWildcardType)suggestion).isSuper()) {
|
||||
return ((PsiWildcardType)suggestion).getBound();
|
||||
}
|
||||
}
|
||||
|
||||
return TypesUtil.substituteBoxAndNormalizeType(suggestion, PsiSubstitutor.EMPTY, null, closure);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -24,8 +24,7 @@ import com.intellij.openapi.vfs.JarFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor
|
||||
|
||||
import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy2_1LibraryName
|
||||
import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy2_2LibraryName
|
||||
import static org.jetbrains.plugins.groovy.util.TestUtils.*
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
@@ -33,6 +32,7 @@ import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy2_2Librar
|
||||
class GroovyLightProjectDescriptor extends DefaultLightProjectDescriptor {
|
||||
public static final GroovyLightProjectDescriptor GROOVY_2_1 = new GroovyLightProjectDescriptor(mockGroovy2_1LibraryName)
|
||||
public static final GroovyLightProjectDescriptor GROOVY_2_2 = new GroovyLightProjectDescriptor(mockGroovy2_2LibraryName)
|
||||
public static final GroovyLightProjectDescriptor GROOVY_2_3 = new GroovyLightProjectDescriptor(mockGroovy2_3LibraryName)
|
||||
|
||||
private final String myLibPath
|
||||
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.resolve
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/02/14
|
||||
*/
|
||||
class TypeInference2_3Test extends TypeInferenceTestBase {
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return GroovyLightProjectDescriptor.GROOVY_2_3
|
||||
}
|
||||
|
||||
public void testContravariantType() throws Exception {
|
||||
doTest('''\
|
||||
import groovy.transform.CompileStatic
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
@CompileStatic
|
||||
class TestCase {
|
||||
|
||||
interface Action<T> {
|
||||
void execute(T thing)
|
||||
}
|
||||
|
||||
static class Wrapper<T> {
|
||||
|
||||
private final T thing
|
||||
|
||||
Wrapper(T thing) {
|
||||
this.thing = thing
|
||||
}
|
||||
|
||||
void contravariantTake(Action<? super T> action) {
|
||||
action.execute(thing)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static <T> Wrapper<T> wrap(Callable<T> callable) {
|
||||
new Wrapper(callable.call())
|
||||
}
|
||||
|
||||
static Integer dub(Integer integer) {
|
||||
integer * 2
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
wrap {
|
||||
1
|
||||
} contravariantTake {
|
||||
dub(i<caret>t) // fails static compile, 'it' is not known to be Integer
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
''', 'java.lang.Integer')
|
||||
}
|
||||
}
|
||||
+2
-26
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -18,31 +18,20 @@ package org.jetbrains.plugins.groovy.lang.resolve
|
||||
import com.intellij.psi.PsiIntersectionType
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiType
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap
|
||||
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.expressions.GrAssignmentExpression
|
||||
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.impl.GrClosureType
|
||||
import org.jetbrains.plugins.groovy.util.TestUtils
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.*
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
public class TypeInferenceTest extends GroovyResolveTestCase {
|
||||
final String basePath = TestUtils.testDataPath + "resolve/inference/"
|
||||
|
||||
@Override
|
||||
protected void setUp() {
|
||||
super.setUp()
|
||||
|
||||
myFixture.addClass("package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> {}");
|
||||
}
|
||||
public class TypeInferenceTest extends TypeInferenceTestBase {
|
||||
|
||||
public void testTryFinallyFlow() {
|
||||
GrReferenceExpression ref = (GrReferenceExpression)configureByFile("tryFinallyFlow/A.groovy").element;
|
||||
@@ -707,17 +696,4 @@ class Any {
|
||||
doExprTest('1f/2.4', 'java.lang.Double')
|
||||
}
|
||||
|
||||
private void doTest(@Language("Groovy") String text, String type) {
|
||||
def file = myFixture.configureByText('_.groovy', text)
|
||||
def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
|
||||
def actual = ref.type
|
||||
assertType(type, actual)
|
||||
}
|
||||
|
||||
private void doExprTest(@Language("Groovy") String text, String expectedType) {
|
||||
GroovyFile file = myFixture.configureByText('_.groovy', text) as GroovyFile
|
||||
GrStatement lastStatement = file.statements.last()
|
||||
assertInstanceOf lastStatement, GrExpression
|
||||
assertType(expectedType, (lastStatement as GrExpression).type)
|
||||
}
|
||||
}
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.resolve
|
||||
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
|
||||
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.util.TestUtils
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 10/02/14
|
||||
*/
|
||||
abstract class TypeInferenceTestBase extends GroovyResolveTestCase {
|
||||
final String basePath = TestUtils.testDataPath + "resolve/inference/"
|
||||
|
||||
@Override
|
||||
protected void setUp() {
|
||||
super.setUp()
|
||||
|
||||
myFixture.addClass("package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> {}");
|
||||
}
|
||||
|
||||
protected void doTest(@Language("Groovy") String text, String type) {
|
||||
def file = myFixture.configureByText('_.groovy', text)
|
||||
def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
|
||||
def actual = ref.type
|
||||
assertType(type, actual)
|
||||
}
|
||||
|
||||
protected void doExprTest(@Language("Groovy") String text, String expectedType) {
|
||||
GroovyFile file = myFixture.configureByText('_.groovy', text) as GroovyFile
|
||||
GrStatement lastStatement = file.statements.last()
|
||||
assertInstanceOf lastStatement, GrExpression
|
||||
assertType(expectedType, (lastStatement as GrExpression).type)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -59,6 +59,7 @@ public abstract class TestUtils {
|
||||
public static final String GROOVY_JAR_18 = "groovy-1.8.0-beta-2.jar";
|
||||
public static final String GROOVY_JAR_21 = "groovy-all-2.1.3.jar";
|
||||
public static final String GROOVY_JAR_22 = "groovy-all-2.2.0-beta-1.jar";
|
||||
public static final String GROOVY_JAR_23 = "groovy-all-2.3.0.jar";
|
||||
|
||||
public static String getMockJdkHome() {
|
||||
return getAbsoluteTestDataPath() + "/mockJDK";
|
||||
@@ -92,6 +93,10 @@ public abstract class TestUtils {
|
||||
return getAbsoluteTestDataPath() + "/mockGroovyLib2.2";
|
||||
}
|
||||
|
||||
private static String getMockGroovy2_3LibraryHome() {
|
||||
return getAbsoluteTestDataPath() + "/mockGroovyLib2.3";
|
||||
}
|
||||
|
||||
public static String getMockGroovy1_8LibraryName() {
|
||||
return getMockGroovy1_8LibraryHome()+"/"+GROOVY_JAR_18;
|
||||
}
|
||||
@@ -104,6 +109,10 @@ public abstract class TestUtils {
|
||||
return getMockGroovy2_2LibraryHome() + "/" + GROOVY_JAR_22;
|
||||
}
|
||||
|
||||
public static String getMockGroovy2_3LibraryName() {
|
||||
return getMockGroovy2_3LibraryHome() + "/" + GROOVY_JAR_23;
|
||||
}
|
||||
|
||||
public static PsiFile createPseudoPhysicalGroovyFile(final Project project, final String text) throws IncorrectOperationException {
|
||||
return createPseudoPhysicalFile(project, TEMP_FILE, text);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user