diff --git a/java/openapi/src/com/intellij/psi/JavaPsiFacade.java b/java/openapi/src/com/intellij/psi/JavaPsiFacade.java index 75f11b58d01d..61fdd8bfd26a 100644 --- a/java/openapi/src/com/intellij/psi/JavaPsiFacade.java +++ b/java/openapi/src/com/intellij/psi/JavaPsiFacade.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -175,7 +175,8 @@ public abstract class JavaPsiFacade { */ public abstract boolean isPartOfPackagePrefix(String packageName); - /* Checks if the specified PSI element belongs to the specified package. + /** + * Checks if the specified PSI element belongs to the specified package. * * @param element the element to check the package for. * @param aPackage the package to check. diff --git a/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java b/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java index 712e64f30ebd..236eb7539a3a 100644 --- a/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java +++ b/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -116,7 +116,7 @@ public abstract class JavaCodeStyleManager { * * @param name the name of the variable. * @param variableKind the kind of the variable. - * @return the stipped-down name. + * @return the stripped-down name. */ public abstract String variableNameToPropertyName(@NonNls String name, VariableKind variableKind); @@ -146,7 +146,7 @@ public abstract class JavaCodeStyleManager { * @param baseNameInfo the base name info for the variable. * @param place the location where the variable will be used. * @param lookForward if true, the existing variables are searched in both directions; if false - only backward - * @return the generated unique name, + * @return the generated unique name */ @NotNull public SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, @@ -163,6 +163,7 @@ public abstract class JavaCodeStyleManager { * @param place the location where the variable will be used. * @param ignorePlaceName if true and place is PsiNamedElement, place.getName() would be still treated as unique name * @param lookForward if true, the existing variables are searched in both directions; if false - only backward @return the generated unique name, + * @return the generated unique name */ @NotNull public abstract SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, PsiElement place, diff --git a/java/openapi/src/com/intellij/psi/javadoc/JavadocTagInfo.java b/java/openapi/src/com/intellij/psi/javadoc/JavadocTagInfo.java index 2d86919346a4..7435213e577b 100644 --- a/java/openapi/src/com/intellij/psi/javadoc/JavadocTagInfo.java +++ b/java/openapi/src/com/intellij/psi/javadoc/JavadocTagInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -29,12 +29,16 @@ public interface JavadocTagInfo { @NonNls String getName(); boolean isInline(); + boolean isValidInContext(PsiElement element); Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix); /** - * Checks the tag value for correctnes. Returns null if correct. Error message otherwise. + * Checks the tag value for correctness. + * + * @param value Doc tag to check. + * @return Returns null if correct, error message otherwise. */ @Nullable String checkTagValue(PsiDocTagValue value); diff --git a/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java b/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java index 4e54b98a5ffb..8e2656131128 100644 --- a/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java +++ b/platform/platform-api/src/com/intellij/openapi/components/PersistentStateComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -22,7 +22,8 @@ import com.intellij.util.xmlb.XmlSerializer; * Every component which would like to persist its state across IDEA restarts * should implement this interface. * - * todo: describe registration procedures + * See JetBrains WIKI + * for detailed description. */ public interface PersistentStateComponent { /** diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java index 0b366bc3cc88..9d1dc4bfd5e8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java @@ -24,10 +24,15 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiType; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +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.*; +import java.util.HashSet; /** * @author peter @@ -67,6 +72,31 @@ public class GrMapType extends GrLiteralClassType { facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : CommonClassNames.JAVA_UTIL_MAP; } + public GrMapType(JavaPsiFacade facade, GlobalSearchScope scope, GrNamedArgument[] args) { + super(LanguageLevel.JDK_1_5, scope, facade); + + myJavaClassName = + facade.findClass(JAVA_UTIL_LINKED_HASH_MAP, scope) != null ? JAVA_UTIL_LINKED_HASH_MAP : CommonClassNames.JAVA_UTIL_MAP; + + myStringEntries = new HashMap(); + myOtherEntries=new ArrayList>(); + + for (GrNamedArgument arg : args) { + GrArgumentLabel label = arg.getLabel(); + if (label == null) continue; + GrExpression expression = arg.getExpression(); + if (expression == null || expression.getType() == null) continue; + + if (label.getName() != null) { + myStringEntries.put(label.getName(), expression.getType()); + } + else if (label.getExpression() != null) { + PsiType type = label.getExpression().getType(); + myOtherEntries.add(new Pair(type, expression.getType())); + } + } + } + @NotNull @Override public PsiClassType rawType() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index e2e8662af8b9..a31c2767ed0d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -364,8 +364,6 @@ public class TypesUtil { public static PsiType getLeastUpperBoundNullable(@Nullable PsiType type1, @Nullable PsiType type2, PsiManager manager) { if (type1 == null) return type2; if (type2 == null) return type1; - if (type1.isAssignableFrom(type2)) return type1; - if (type2.isAssignableFrom(type1)) return type2; return getLeastUpperBound(type1, type2, manager); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java index 3edd4b55a4f4..ce36af40c433 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrClosureSignatureUtil.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.types; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; @@ -41,6 +42,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCurriedClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; +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.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -645,4 +647,56 @@ public class GrClosureSignatureUtil { @NotNull GrClosureSignature signature) { return generateAllMethodSignaturesByClosureSignature(name, signature, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); } + + @Nullable + public static PsiType getTypeByTypeArg(ArgInfo arg, PsiManager manager, GlobalSearchScope resolveScope) { + if (arg.isMultiArg) { + if (arg.args.size() == 0) return PsiType.getJavaLangObject(manager, resolveScope).createArrayType(); + PsiType leastUpperBound = null; + + for (PsiType type : arg.args) { + leastUpperBound = TypesUtil.getLeastUpperBoundNullable(leastUpperBound, type, manager); + } + if (leastUpperBound == null) return null; + return leastUpperBound.createArrayType(); + } + else { + if (arg.args.size() > 0) return arg.args.get(0); + return null; + } + } + + @Nullable + public static PsiType getTypeByArg(ArgInfo arg, PsiManager manager, GlobalSearchScope resolveScope) { + if (arg.isMultiArg) { + if (arg.args.size() == 0) return PsiType.getJavaLangObject(manager, resolveScope).createArrayType(); + PsiType leastUpperBound = null; + PsiElement first = arg.args.get(0); + if (first instanceof GrNamedArgument) { + GrNamedArgument[] args=new GrNamedArgument[arg.args.size()]; + for (int i = 0, size = arg.args.size(); i < size; i++) { + args[i] = (GrNamedArgument)arg.args.get(i); + } + return new GrMapType(JavaPsiFacade.getInstance(manager.getProject()), resolveScope, args); + } + else { + for (PsiElement elem : arg.args) { + if (elem instanceof GrExpression) { + leastUpperBound = TypesUtil.getLeastUpperBoundNullable(leastUpperBound, ((GrExpression)elem).getType(), manager); + } + } + if (leastUpperBound == null) return null; + return leastUpperBound.createArrayType(); + } + } + else { + if (arg.args.size() == 0) return null; + PsiElement elem = arg.args.get(0); + if (elem instanceof GrExpression) { + return ((GrExpression)elem).getType(); + } + return null; + } + } + } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnnotationGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnnotationGenerator.java index 0bbbed408b9d..c3e4dc4e74bd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnnotationGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnnotationGenerator.java @@ -29,9 +29,9 @@ public class AnnotationGenerator extends Generator { private final ExpressionContext context; private final ExpressionGenerator expressionGenerator; - public AnnotationGenerator(StringBuilder builder, Project project) { + public AnnotationGenerator(StringBuilder builder, ExpressionContext context) { this.builder = builder; - this.context = new ExpressionContext(project); + this.context = context.extend(); expressionGenerator = new ExpressionGenerator(builder, context); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java index a080c47e4260..9314c88f6eb9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java @@ -105,7 +105,7 @@ public class AnonymousFromMapGenerator { PsiType returnType; if (found != null) { - returnType = substitutor.substitute(TypeProvider.getReturnType(found)); + returnType = substitutor.substitute(context.typeProvider.getReturnType(found)); } else { returnType = signature.getReturnType(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java index 3da9d806a7b2..ee6a88305a62 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java @@ -186,9 +186,9 @@ public class ClassGenerator { private static boolean shouldBeGenerated(PsiMethod method) { for (PsiMethod psiMethod : method.findSuperMethods()) { if (!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) { - final PsiType type = TypeProvider.getReturnType(method); - final PsiType superType = TypeProvider.getReturnType(psiMethod); - if (!superType.isAssignableFrom(type)) { + final PsiType type = method.getReturnType(); + final PsiType superType = psiMethod.getReturnType(); + if (type != null && superType != null && !superType.isAssignableFrom(type)) { return false; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index 307b32f2a019..2f2c343e0b51 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -120,7 +120,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { //append return type if (!method.isConstructor()) { - PsiType retType = TypeProvider.getReturnType(method); + PsiType retType = context.typeProvider.getReturnType(method); /* if (!method.hasModifierProperty(PsiModifier.STATIC)) { @@ -161,7 +161,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { builder.append("default "); GrAnnotationMemberValue defaultValue = defaultAnnotationValue.getDefaultValue(); if (defaultValue != null) { - defaultValue.accept(new AnnotationGenerator(builder, context.project)); + defaultValue.accept(new AnnotationGenerator(builder, context)); } } } @@ -206,7 +206,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { builder.append("this"); } else { - if (TypeProvider.getReturnType(method) != PsiType.VOID) { + if (context.typeProvider.getReturnType(method) != PsiType.VOID) { builder.append("return "); } builder.append(method.getName()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java index ec00a8787943..6bcb3aee7aea 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.refactoring.convertToJava; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.util.containers.hash.HashSet; -import org.codehaus.groovy.util.ManagedConcurrentMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection; import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils; @@ -91,7 +90,7 @@ public class CodeBlockGenerator extends Generator { boolean shouldInsertReturnNull = false; myExitPoints.clear(); - PsiType returnType = TypeProvider.getReturnType(method); + PsiType returnType = context.typeProvider.getReturnType(method); if (!method.isConstructor() && returnType != PsiType.VOID) { myExitPoints.addAll(ControlFlowUtils.collectReturns(block)); shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) && @@ -121,7 +120,7 @@ public class CodeBlockGenerator extends Generator { for (GrParameter parameter : parameters) { if (context.analyzedVars.toWrap(parameter)) { StringBuilder typeText = new StringBuilder(GroovyCommonClassNames.GROOVY_LANG_REFERENCE); - GenerationUtil.writeTypeParameters(typeText, new PsiType[]{TypeProvider.getParameterType(parameter)}, method, + GenerationUtil.writeTypeParameters(typeText, new PsiType[]{context.typeProvider.getParameterType(parameter)}, method, new GeneratorClassNameProvider()); builder.append("final ").append(typeText).append(' ').append(context.analyzedVars.toVarName(parameter)) .append(" = new ").append(typeText).append('(').append(parameter.getName()).append(");\n"); @@ -193,7 +192,7 @@ public class CodeBlockGenerator extends Generator { return; } - final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context.project); + final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context); returnValue.accept(expressionGenerator); StringBuilder builder = new StringBuilder(); builder.append("return ").append(expressionGenerator.getBuilder()).append(";"); //todo add casts to return type @@ -209,7 +208,7 @@ public class CodeBlockGenerator extends Generator { @Override public void visitAssertStatement(GrAssertStatement assertStatement) { final GrExpression assertion = assertStatement.getAssertion(); - final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context.project); + final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context); assertion.accept(expressionGenerator); final StringBuilder builder = new StringBuilder("assert ").append(expressionGenerator.getBuilder()).append(";"); writeStatement(builder, assertStatement, expressionGenerator.getContext()); @@ -218,7 +217,7 @@ public class CodeBlockGenerator extends Generator { @Override public void visitThrowStatement(GrThrowStatement throwStatement) { final GrExpression exception = throwStatement.getException(); - final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context.project); + final ExpressionGenerator expressionGenerator = new ExpressionGenerator(context); exception.accept(expressionGenerator); final StringBuilder builder = new StringBuilder("throw ").append(expressionGenerator.getBuilder()).append(";"); //todo add exception to method 'throws' list @@ -307,7 +306,7 @@ public class CodeBlockGenerator extends Generator { final GrVariable declaredVariable = clause.getDeclaredVariable(); LOG.assertTrue(declaredVariable != null); - writeVariableWithoutSemicolonAndInitializer(builder, declaredVariable); + writeVariableWithoutSemicolonAndInitializer(builder, declaredVariable, context); builder.append(" : "); if (expression != null) { final ExpressionContext context = forContext.copy(); @@ -322,7 +321,7 @@ public class CodeBlockGenerator extends Generator { if (initialization instanceof GrParameter) { StringBuilder partBuilder = new StringBuilder(); - writeVariableWithoutSemicolonAndInitializer(partBuilder, (GrParameter)initialization); + writeVariableWithoutSemicolonAndInitializer(partBuilder, (GrParameter)initialization, context); final GrExpression initializer = ((GrParameter)initialization).getDefaultInitializer(); if (initializer != null) { final ExpressionContext partContext = forContext.copy(); @@ -371,9 +370,9 @@ public class CodeBlockGenerator extends Generator { builder.append(visitor.getBuilder()); } - private static void writeVariableWithoutSemicolonAndInitializer(StringBuilder builder, GrVariable var) { + private static void writeVariableWithoutSemicolonAndInitializer(StringBuilder builder, GrVariable var, ExpressionContext context) { ModifierListGenerator.writeModifiers(builder, var.getModifierList()); - GenerationUtil.writeType(builder, TypeProvider.getVarType(var), var); + GenerationUtil.writeType(builder, context.typeProvider.getVarType(var), var); builder.append(" ").append(var.getName()); } @@ -422,7 +421,7 @@ public class CodeBlockGenerator extends Generator { public void visitCatchClause(GrCatchClause catchClause) { final GrParameter parameter = catchClause.getParameter(); builder.append("catch ("); - writeVariableWithoutSemicolonAndInitializer(builder, parameter); + writeVariableWithoutSemicolonAndInitializer(builder, parameter, context); builder.append(") "); final GrOpenBlock body = catchClause.getBody(); if (body != null) { @@ -494,7 +493,7 @@ public class CodeBlockGenerator extends Generator { final GrModifierList modifierList = variableDeclaration.getModifierList(); for (final GrVariable v : variables) { ModifierListGenerator.writeModifiers(builder, modifierList); - final PsiType type = TypeProvider.getVarType(v); + final PsiType type = context.typeProvider.getVarType(v); GenerationUtil.writeType(builder, type, variableDeclaration); builder.append(" ").append(v.getName()); builder.append(" = ").append(iteratorName).append(".hasNext() ? ").append(iteratorName).append(".next() : null;"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java index 0a6c86c9e329..8ebe7347b37a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionContext.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.refactoring.convertToJava; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.util.containers.hash.HashMap; import com.intellij.util.containers.hash.HashSet; @@ -30,19 +29,21 @@ class ExpressionContext implements Cloneable { List myStatements = new ArrayList(); Set myUsedVarNames; LocalVarAnalyzer.Result analyzedVars = LocalVarAnalyzer.initialResult(); + TypeProvider typeProvider; Project project; private Map myProps = new HashMap(); private static final String myShouldInsertCurlyBrackets = "shouldInsertCurly"; private static final String myInAnonymousContext = "inAnonymousContext"; - ExpressionContext(Project project, Set usedVarNames) { + private ExpressionContext(Project project, Set usedVarNames) { this.project = project; myUsedVarNames = usedVarNames; } ExpressionContext(Project project) { this(project, new HashSet()); + typeProvider = new TypeProvider(); } @Override @@ -54,6 +55,7 @@ class ExpressionContext implements Cloneable { final ExpressionContext expressionContext = new ExpressionContext(project, myUsedVarNames); expressionContext.myProps.putAll(myProps); expressionContext.analyzedVars = analyzedVars; + expressionContext.typeProvider = typeProvider; return expressionContext; } @@ -63,6 +65,7 @@ class ExpressionContext implements Cloneable { final ExpressionContext expressionContext = new ExpressionContext(project, usedVarNames); expressionContext.myProps.putAll(myProps); expressionContext.analyzedVars = analyzedVars; + expressionContext.typeProvider = typeProvider; return expressionContext; } 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 6d09a6d5ad59..262352fd4390 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 @@ -16,7 +16,6 @@ package org.jetbrains.plugins.groovy.refactoring.convertToJava; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightElement; @@ -82,8 +81,11 @@ public class ExpressionGenerator extends Generator { factory = GroovyPsiElementFactory.getInstance(context.project); } - public ExpressionGenerator(Project project) { - this(new StringBuilder(), new ExpressionContext(project)); + public ExpressionGenerator(ExpressionContext context) { + this.builder = new StringBuilder(); + this.context = context; + + factory = GroovyPsiElementFactory.getInstance(context.project); } @Override 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 335b3db02152..a7bc173522fa 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 @@ -289,10 +289,15 @@ public class GenerationUtil { if (!classNameProvider.forStubs()) { ModifierListGenerator.writeModifiers(text, parameter.getModifierList(), ModifierListGenerator.JAVA_MODIFIERS, true); } - if (context != null && context.analyzedVars.toMakeFinal(parameter)) { - text.append(PsiModifier.FINAL).append(' '); + if (context != null) { + if (context.analyzedVars.toMakeFinal(parameter)) { + text.append(PsiModifier.FINAL).append(' '); + } + writeType(text, context.typeProvider.getParameterType(parameter), parameter, classNameProvider); + } + else { + writeType(text, parameter.getType(), parameter, classNameProvider); } - writeType(text, TypeProvider.getParameterType(parameter), parameter, classNameProvider); text.append(" "); text.append(parameter.getName()); @@ -425,7 +430,7 @@ public class GenerationUtil { } static void writeVariableSeparately(GrVariable variable, StringBuilder builder, ExpressionContext expressionContext) { - PsiType type = TypeProvider.getVarType(variable); + PsiType type = expressionContext.typeProvider.getVarType(variable); ModifierListGenerator.writeModifiers(builder, variable.getModifierList()); PsiType originalType = type; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ModifierListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ModifierListGenerator.java index f324e11de872..b387ebb03f78 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ModifierListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ModifierListGenerator.java @@ -83,7 +83,7 @@ public class ModifierListGenerator { if (writeAnnotations && modifierList instanceof GrModifierList) { GrAnnotation[] annotations = ((GrModifierList)modifierList).getAnnotations(); - AnnotationGenerator annotationGenerator = new AnnotationGenerator(builder, modifierList.getProject()); + AnnotationGenerator annotationGenerator = new AnnotationGenerator(builder, new ExpressionContext(modifierList.getProject())); wasAddedModifiers = annotations.length > 0; for (GrAnnotation annotation : annotations) { annotation.accept(annotationGenerator); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java index 44bd0dabf4b5..d13d56a72ddf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/StubGenerator.java @@ -40,6 +40,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrCo import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import java.util.*; @@ -97,7 +98,7 @@ public class StubGenerator implements ClassItemGenerator { for (int j = 0; j < superParams.length; j++) { if (j > 0) text.append(", "); text.append("("); - final PsiType type = TypeProvider.getParameterType(superParams[j]); + final PsiType type = superParams[j].getType(); writeType(text, substitutor.substitute(type), invocation, classNameProvider); text.append(")").append(GroovyToJavaGenerator.getDefaultValueText(type.getCanonicalText())); } @@ -185,7 +186,10 @@ public class StubGenerator implements ClassItemGenerator { } //append return type - PsiType retType = TypeProvider.getReturnType(method, true); + PsiType retType = method.getReturnType(); + if (retType == null) { + retType = TypesUtil.getJavaLangObject(method); + } if (!method.hasModifierProperty(PsiModifier.STATIC)) { final List superSignatures = method.findSuperMethodSignaturesIncludingStatic(true); @@ -320,7 +324,7 @@ public class StubGenerator implements ClassItemGenerator { final LightMethodBuilder builder = new LightMethodBuilder(method.getManager(), method.getName()); substitutor = substitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(baseClass, typeDefinition, PsiSubstitutor.EMPTY)); for (PsiParameter parameter : method.getParameterList().getParameters()) { - builder.addParameter(StringUtil.notNullize(parameter.getName()), substitutor.substitute(TypeProvider.getParameterType(parameter))); + builder.addParameter(StringUtil.notNullize(parameter.getName()), substitutor.substitute(parameter.getType())); } builder.setReturnType(substitutor.substitute(method.getReturnType())); for (String modifier : STUB_MODIFIERS) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java index 24879e233640..19fbe1d225d3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java @@ -15,38 +15,39 @@ */ package org.jetbrains.plugins.groovy.refactoring.convertToJava; -import com.intellij.psi.PsiMethod; -import com.intellij.psi.PsiParameter; -import com.intellij.psi.PsiType; -import com.intellij.psi.PsiVariable; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.MethodReferencesSearch; +import com.intellij.util.Processor; +import com.intellij.util.containers.HashMap; +import gnu.trove.TIntArrayList; +import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; 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.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import java.util.Map; + /** * @author Medvedev Max */ public class TypeProvider { + private final Map inferredTypes = new HashMap(); - private TypeProvider() { + public TypeProvider() { } @NotNull - public static PsiType getReturnType(PsiMethod method) { - return getReturnType(method, false); - } - - @NotNull - public static PsiType getReturnType(PsiMethod method, boolean forStubs) { - - if (forStubs) { - PsiType returnType = method.getReturnType(); - if (returnType != null) return returnType; - return TypesUtil.getJavaLangObject(method); - } + public PsiType getReturnType(PsiMethod method) { if (method instanceof GrMethod) { GrTypeElement typeElement = ((GrMethod)method).getReturnTypeElementGroovy(); if (typeElement != null) return typeElement.getType(); @@ -59,7 +60,7 @@ public class TypeProvider { } @NotNull - public static PsiType getVarType(GrVariable variable) { + public PsiType getVarType(GrVariable variable) { PsiType type = variable.getDeclaredType(); if (type == null) { type = variable.getTypeGroovy(); @@ -71,7 +72,77 @@ public class TypeProvider { } @NotNull - public static PsiType getParameterType(PsiParameter parameter) { - return parameter.getType(); //todo make smarter + public PsiType getParameterType(PsiParameter parameter) { + if (!(parameter instanceof GrParameter)) { + return parameter.getType(); + } + /*GrTypeElement typeElementGroovy = ((GrParameter)parameter).getTypeElementGroovy(); + if (typeElementGroovy != null) { + return parameter.getType(); + }*/ + + PsiElement parent = parameter.getParent(); + if (!(parent instanceof GrParameterList)) return parameter.getType(); + + PsiElement pparent = parent.getParent(); + if (!(pparent instanceof GrMethod)) return parameter.getType(); + + PsiType[] types = inferMethodParameters((GrMethod)pparent); + return types[((GrParameterList)parent).getParameterNumber((GrParameter)parameter)]; + } + + private PsiType[] inferMethodParameters(GrMethod method) { + PsiType[] psiTypes = inferredTypes.get(method); + if (psiTypes != null) return psiTypes; + + final GrParameter[] parameters = method.getParameters(); + + final TIntArrayList paramInds = new TIntArrayList(parameters.length); + final PsiType[] types = new PsiType[parameters.length]; + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].getTypeElementGroovy() == null) { + paramInds.add(i); + } else { + types[i] = parameters[i].getType(); + } + } + + if (paramInds.size() > 0) { + final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY); + MethodReferencesSearch.search(method, true).forEach(new Processor() { + @Override + public boolean process(PsiReference psiReference) { + final PsiElement element = psiReference.getElement(); + final PsiManager manager = element.getManager(); + final GlobalSearchScope resolveScope = element.getResolveScope(); + + if (element instanceof GrReferenceExpression) { + final GrCall call = (GrCall)element.getParent(); + final GrClosureSignatureUtil.ArgInfo[] argInfos = GrClosureSignatureUtil + .mapParametersToArguments(signature, call.getArgumentList(), ((GrReferenceExpression)element), call.getClosureArguments()); + + if (argInfos == null) return true; + paramInds.forEach(new TIntProcedure() { + @Override + public boolean execute(int i) { + PsiType type = GrClosureSignatureUtil.getTypeByArg(argInfos[i], manager, resolveScope); + types[i] = TypesUtil.getLeastUpperBoundNullable(type, types[i], manager); + return true; + } + }); + } + return true; + } + }); + } + paramInds.forEach(new TIntProcedure() { + @Override + public boolean execute(int i) { + if (types[i]==null) types[i] = parameters[i].getType(); + return true; + } + }); + inferredTypes.put(method, types); + return types; } } diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/concurency.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/concurency.java index 398d6e05b5d9..c5ef7999ca54 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/concurency.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/concurency.java @@ -32,7 +32,7 @@ return null; } -public synchronized void out(java.lang.Object message) { +public synchronized void out(groovy.lang.GString message) { println(message); }