mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] LUB of numeric types (IDEA-134930)
This commit is contained in:
+29
-16
@@ -29,7 +29,6 @@ import com.intellij.util.containers.ComparatorUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -54,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.HardcodedGroovyMethodConstants.*;
|
||||
@@ -179,6 +179,15 @@ public class TypesUtil {
|
||||
TYPE_TO_RANK.put(CommonClassNames.JAVA_LANG_NUMBER, 9);
|
||||
}
|
||||
|
||||
private static final List<PsiType> LUB_NUMERIC_TYPES = ContainerUtil.newArrayList(
|
||||
PsiType.BYTE,
|
||||
PsiType.SHORT,
|
||||
PsiType.INT,
|
||||
PsiType.LONG,
|
||||
PsiType.FLOAT,
|
||||
PsiType.DOUBLE
|
||||
);
|
||||
|
||||
static {
|
||||
ourQNameToUnboxed.put(CommonClassNames.JAVA_LANG_BOOLEAN, PsiType.BOOLEAN);
|
||||
ourQNameToUnboxed.put(CommonClassNames.JAVA_LANG_BYTE, PsiType.BYTE);
|
||||
@@ -191,21 +200,6 @@ public class TypesUtil {
|
||||
ourQNameToUnboxed.put(CommonClassNames.JAVA_LANG_VOID, PsiType.VOID);
|
||||
}
|
||||
|
||||
|
||||
private static final TIntObjectHashMap<String> RANK_TO_TYPE = new TIntObjectHashMap<>();
|
||||
|
||||
static {
|
||||
RANK_TO_TYPE.put(1, CommonClassNames.JAVA_LANG_INTEGER);
|
||||
RANK_TO_TYPE.put(2, CommonClassNames.JAVA_LANG_INTEGER);
|
||||
RANK_TO_TYPE.put(3, CommonClassNames.JAVA_LANG_INTEGER);
|
||||
RANK_TO_TYPE.put(4, CommonClassNames.JAVA_LANG_LONG);
|
||||
RANK_TO_TYPE.put(5, GroovyCommonClassNames.JAVA_MATH_BIG_INTEGER);
|
||||
RANK_TO_TYPE.put(6, GroovyCommonClassNames.JAVA_MATH_BIG_DECIMAL);
|
||||
RANK_TO_TYPE.put(7, CommonClassNames.JAVA_LANG_DOUBLE);
|
||||
RANK_TO_TYPE.put(8, CommonClassNames.JAVA_LANG_DOUBLE);
|
||||
RANK_TO_TYPE.put(9, CommonClassNames.JAVA_LANG_NUMBER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated see {@link #canAssign}
|
||||
*/
|
||||
@@ -499,6 +493,10 @@ public class TypesUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiType getLeastUpperBound(@NotNull PsiType type1, @NotNull PsiType type2, PsiManager manager) {
|
||||
{
|
||||
PsiType numericLUB = getNumericLUB(type1, type2);
|
||||
if (numericLUB != null) return numericLUB;
|
||||
}
|
||||
if (type1 instanceof GrTupleType && type2 instanceof GrTupleType) {
|
||||
GrTupleType tuple1 = (GrTupleType)type1;
|
||||
GrTupleType tuple2 = (GrTupleType)type2;
|
||||
@@ -565,6 +563,21 @@ public class TypesUtil {
|
||||
return GenericsUtil.getLeastUpperBound(type1, type2, manager);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getNumericLUB(@Nullable PsiType type1, @Nullable PsiType type2) {
|
||||
PsiPrimitiveType unboxedType1 = PsiPrimitiveType.getUnboxedType(type1);
|
||||
PsiPrimitiveType unboxedType2 = PsiPrimitiveType.getUnboxedType(type2);
|
||||
if (unboxedType1 != null && unboxedType2 != null) {
|
||||
int i1 = LUB_NUMERIC_TYPES.indexOf(unboxedType1);
|
||||
int i2 = LUB_NUMERIC_TYPES.indexOf(unboxedType2);
|
||||
if (i1 >= 0 && i2 >= 0) {
|
||||
if (i1 > i2) return type1;
|
||||
if (i2 > i1) return type2;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean checkEmptyListAndList(PsiType type1, PsiType type2) {
|
||||
if (type1 instanceof GrTupleType) {
|
||||
PsiType[] types = ((GrTupleType)type1).getComponentTypes();
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 groovy.transform.CompileStatic
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.LightGroovyTestCase
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
|
||||
|
||||
@CompileStatic
|
||||
class GrNumericLUBTypeTest extends LightGroovyTestCase {
|
||||
|
||||
final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST
|
||||
|
||||
@Override
|
||||
void setUp() throws Exception {
|
||||
super.setUp()
|
||||
fixture.addFileToProject '''constants.groovy''', '''\
|
||||
interface Constants {
|
||||
Byte nB = 0
|
||||
Short nS = 0
|
||||
Integer nI = 0
|
||||
Long nL = 0
|
||||
Float nF = 0
|
||||
Double nD = 0
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
private void doTest(String expressionText, String expectedType) {
|
||||
def file = fixture.configureByText('_.groovy', """\
|
||||
import static Constants.*
|
||||
$expressionText
|
||||
""") as GroovyFile
|
||||
def expression = file.statements.last() as GrExpression
|
||||
assert expression.type.equalsToText(expectedType): "'$expression.text' : $expression.type"
|
||||
}
|
||||
|
||||
void 'test elvis types'() {
|
||||
[
|
||||
// Byte
|
||||
'nB ?: nB': 'java.lang.Byte',
|
||||
'nB ?: nS': 'java.lang.Short',
|
||||
'nB ?: nI': 'java.lang.Integer',
|
||||
'nB ?: nL': 'java.lang.Long',
|
||||
'nB ?: nF': 'java.lang.Float',
|
||||
'nB ?: nD': 'java.lang.Double',
|
||||
|
||||
// Short
|
||||
'nS ?: nB': 'java.lang.Short',
|
||||
'nS ?: nS': 'java.lang.Short',
|
||||
'nS ?: nI': 'java.lang.Integer',
|
||||
'nS ?: nL': 'java.lang.Long',
|
||||
'nS ?: nF': 'java.lang.Float',
|
||||
'nS ?: nD': 'java.lang.Double',
|
||||
|
||||
// Integer
|
||||
'nI ?: nB': 'java.lang.Integer',
|
||||
'nI ?: nS': 'java.lang.Integer',
|
||||
'nI ?: nI': 'java.lang.Integer',
|
||||
'nI ?: nL': 'java.lang.Long',
|
||||
'nI ?: nF': 'java.lang.Float',
|
||||
'nI ?: nD': 'java.lang.Double',
|
||||
|
||||
// Long
|
||||
'nL ?: nB': 'java.lang.Long',
|
||||
'nL ?: nS': 'java.lang.Long',
|
||||
'nL ?: nI': 'java.lang.Long',
|
||||
'nL ?: nL': 'java.lang.Long',
|
||||
'nL ?: nF': 'java.lang.Float',
|
||||
'nL ?: nD': 'java.lang.Double',
|
||||
|
||||
// Float
|
||||
'nF ?: nB': 'java.lang.Float',
|
||||
'nF ?: nS': 'java.lang.Float',
|
||||
'nF ?: nI': 'java.lang.Float',
|
||||
'nF ?: nL': 'java.lang.Float',
|
||||
'nF ?: nF': 'java.lang.Float',
|
||||
'nF ?: nD': 'java.lang.Double',
|
||||
|
||||
// Double
|
||||
'nD ?: nB': 'java.lang.Double',
|
||||
'nD ?: nS': 'java.lang.Double',
|
||||
'nD ?: nI': 'java.lang.Double',
|
||||
'nD ?: nL': 'java.lang.Double',
|
||||
'nD ?: nF': 'java.lang.Double',
|
||||
'nD ?: nD': 'java.lang.Double',
|
||||
].each {
|
||||
doTest it.key, it.value
|
||||
}
|
||||
}
|
||||
|
||||
// same as elvis
|
||||
void 'test ternary types'() {
|
||||
[
|
||||
'42 ? nB : nB': 'java.lang.Byte',
|
||||
'42 ? nB : nS': 'java.lang.Short',
|
||||
'42 ? nB : nI': 'java.lang.Integer',
|
||||
'42 ? nB : nL': 'java.lang.Long',
|
||||
'42 ? nB : nF': 'java.lang.Float',
|
||||
'42 ? nB : nD': 'java.lang.Double',
|
||||
].each {
|
||||
doTest it.key, it.value
|
||||
}
|
||||
}
|
||||
|
||||
// same as elvis
|
||||
void 'test if branches assignment'() {
|
||||
[
|
||||
'def a; if (42) { a = nB } else { a = nB }; a': 'java.lang.Byte',
|
||||
'def a; if (42) { a = nB } else { a = nS }; a': 'java.lang.Short',
|
||||
'def a; if (42) { a = nB } else { a = nI }; a': 'java.lang.Integer',
|
||||
'def a; if (42) { a = nB } else { a = nL }; a': 'java.lang.Long',
|
||||
'def a; if (42) { a = nB } else { a = nF }; a': 'java.lang.Float',
|
||||
'def a; if (42) { a = nB } else { a = nD }; a': 'java.lang.Double',
|
||||
].each {
|
||||
doTest it.key, it.value
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user