diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultListOrMapTypeCalculator.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultListOrMapTypeCalculator.kt index dff8c0da6d4b..86f1a6d81aa5 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultListOrMapTypeCalculator.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/typing/DefaultListOrMapTypeCalculator.kt @@ -16,11 +16,13 @@ package org.jetbrains.plugins.groovy.lang.typing import com.intellij.openapi.util.RecursionManager -import com.intellij.psi.* +import com.intellij.psi.CommonClassNames +import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiType import com.intellij.psi.util.InheritanceUtil.isInheritor import com.intellij.psi.util.PsiUtil.substituteTypeParameter 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.impl.GrMapType import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil @@ -34,7 +36,7 @@ class DefaultListOrMapTypeCalculator : GrTypeCalculator { return getMapTypeFromDiamond(expression) ?: GrMapType.createFromNamedArgs(expression, expression.namedArguments) } else { - return getArrayTypeFromDeclaration(expression) ?: getListTypeFromDiamond(expression) ?: getTupleType(expression) + return getListTypeFromDiamond(expression) ?: getTupleType(expression) } } @@ -74,11 +76,6 @@ class DefaultListOrMapTypeCalculator : GrTypeCalculator { ) } - private fun getArrayTypeFromDeclaration(expression: GrListOrMap): PsiType? { - val parent = expression.parent?.parent as? GrVariableDeclaration - return parent?.typeElementGroovy?.type as? PsiArrayType - } - private fun getTupleType(expression: GrListOrMap): PsiType? { val initializers = expression.initializers diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index a95e8d4fb02e..07cac514410c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -90,19 +90,21 @@ public class ExpressionGenerator extends Generator { private final GroovyPsiElementFactory factory; private final ExpressionContext context; + private final @Nullable PsiType expectedType; - public ExpressionGenerator(StringBuilder builder, ExpressionContext context) { + public ExpressionGenerator(StringBuilder builder, ExpressionContext context, @Nullable PsiType expectedType) { this.builder = builder; this.context = context; + this.expectedType = expectedType; + this.factory = GroovyPsiElementFactory.getInstance(context.project); + } - factory = GroovyPsiElementFactory.getInstance(context.project); + public ExpressionGenerator(StringBuilder builder, ExpressionContext context) { + this(builder, context, null); } public ExpressionGenerator(ExpressionContext context) { - this.builder = new StringBuilder(); - this.context = context; - - factory = GroovyPsiElementFactory.getInstance(context.project); + this(new StringBuilder(), context); } @Override @@ -1172,16 +1174,14 @@ public class ExpressionGenerator extends Generator { } else { TypeWriter.writeTypeForNew(builder, type, typeCastExpression); - builder.append('{'); + final PsiType newExpectedType = expectedType instanceof PsiArrayType ? ((PsiArrayType)expectedType).getComponentType() : null; + final ExpressionGenerator childGenerator = new ExpressionGenerator(builder, context, newExpectedType); for (GrExpression initializer : initializers) { - initializer.accept(this); + initializer.accept(childGenerator); builder.append(", "); } - if (initializers.length > 0) { - builder.delete(builder.length() - 2, builder.length()); - //builder.removeFromTheEnd(2); - } + builder.delete(builder.length() - 2, builder.length()); builder.append('}'); } return; @@ -1407,8 +1407,7 @@ public class ExpressionGenerator extends Generator { public void visitListOrMap(@NotNull GrListOrMap listOrMap) { final PsiType type = listOrMap.getType(); - //can be PsiArrayType or GrLiteralClassType - LOG.assertTrue(type instanceof GrLiteralClassType || type instanceof PsiArrayType || type instanceof PsiClassType); + LOG.assertTrue(type instanceof GrLiteralClassType || type instanceof PsiClassType); if (listOrMap.isMap()) { if (listOrMap.getNamedArguments().length == 0) { @@ -1448,13 +1447,16 @@ public class ExpressionGenerator extends Generator { } } - private static PsiType getTypeToUseByList(GrListOrMap listOrMap, PsiType type) { + private PsiType getTypeToUseByList(GrListOrMap listOrMap, PsiType type) { if (isImplicitlyCastedToArray(listOrMap)) { PsiType iterable = ClosureParameterEnhancer.findTypeForIteration(listOrMap, listOrMap); if (iterable != null) { return new PsiArrayType(iterable); } } + else if (expectedType instanceof PsiArrayType) { + return expectedType; + } if (type instanceof PsiClassType) { PsiClass resolved = ((PsiClassType)type).resolve(); if (resolved != null && CommonClassNames.JAVA_UTIL_LIST.equals(resolved.getQualifiedName())) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java index 7517d9443127..cc296eab9e42 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -23,6 +23,7 @@ import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; @@ -33,6 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; 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.formatter.GrControlStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -40,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaratio 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.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; @@ -55,6 +58,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProces import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; @@ -434,22 +438,42 @@ public class GenerationUtil { } builder.append('('); } - final PsiType iType = getDeclaredType(initializer, expressionContext); - //generate cast - if (original != null && iType != null && !TypesUtil.isAssignable(original, iType, initializer)) { + if (isCastNeeded(original, initializer, expressionContext)) { builder.append('('); TypeWriter.writeType(builder, original, initializer); builder.append(')'); } - initializer.accept(new ExpressionGenerator(builder, expressionContext)); + initializer.accept(new ExpressionGenerator(builder, expressionContext, original)); if (wrapped) { builder.append(')'); } } } + private static boolean isCastNeeded(PsiType target, GrExpression initializer, ExpressionContext expressionContext) { + if (target == null) return false; + final PsiType iType = getDeclaredType(initializer, expressionContext); + if (iType == null) return false; + if (TypeConversionUtil.isAssignable(target, iType)) return false; + + if (initializer instanceof GrLiteral) { + Object value = ((GrLiteral)initializer).getValue(); + if (value instanceof BigDecimal && Double.isFinite(((BigDecimal)value).doubleValue())) { + return !TypeConversionUtil.isAssignable(target, PsiType.DOUBLE); + } + else if (value instanceof String && ((String)value).length() == 1) { + return !PsiType.CHAR.equals(PsiPrimitiveType.getOptionallyUnboxedType(target)); + } + } + else if (initializer instanceof GrListOrMap && target instanceof PsiArrayType) { + GrListOrMap listOrMap = (GrListOrMap)initializer; + return listOrMap.isMap(); + } + return true; + } + static void writeVariableSeparately(GrVariable variable, StringBuilder builder, ExpressionContext expressionContext) { PsiType type = expressionContext.typeProvider.getVarType(variable); ModifierListGenerator.writeModifiers(builder, variable.getModifierList()); @@ -583,12 +607,6 @@ public class GenerationUtil { final GrExpression invokedExpression = ((GrMethodCall)expression).getInvokedExpression(); return getDeclaredType(invokedExpression, context); } - else if (expression instanceof GrBinaryExpression) { - final GroovyResolveResult result = PsiImplUtil.extractUniqueResult(((GrBinaryExpression)expression).multiResolve(false)); - if (result.getElement() instanceof PsiMethod) { - return getDeclaredType((PsiMethod)result.getElement(), result.getSubstitutor(), context); - } - } else if (expression instanceof GrIndexProperty) { final GroovyResolveResult result = ((GrIndexProperty)expression).advancedResolve(); if (result.getElement() instanceof PsiMethod) { diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.groovy index 25e8c7231f77..0eac75c510a5 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.groovy +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.groovy @@ -15,4 +15,5 @@ */ def list = [] int[] arr = [] -List strings = [] \ No newline at end of file +List strings = [] +int[] arr2 = list \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java index f8207e0a1033..fbd6a261cad5 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/emptyList.java @@ -1,3 +1,4 @@ java.util.List list = new java.util.ArrayList(); java.lang.Integer[] arr = new java.lang.Integer[0]; java.util.List strings = new java.util.ArrayList(); +java.lang.Integer[] arr2 = (java.lang.Integer[])list; \ No newline at end of file