blob: 61ba3996078bbe53874cc19893f595b69230dde7 [file] [log] [blame]
/*
* 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.refactoring.convertToJava;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
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.formatter.GrControlStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
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.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;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor;
import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator;
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
* @author Maxim.Medvedev
*/
public class GenerationUtil {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil");
private GenerationUtil() {
}
public static void writeTypeParameters(StringBuilder builder,
PsiType[] parameters,
PsiElement context,
ClassNameProvider classNameProvider) {
if (parameters.length == 0) return;
builder.append('<');
for (PsiType parameter : parameters) {
if (parameter instanceof PsiPrimitiveType) {
parameter = TypesUtil.boxPrimitiveType(parameter, context.getManager(), context.getResolveScope(), true);
}
TypeWriter.writeType(builder, parameter, context, classNameProvider);
builder.append(", ");
}
builder.delete(builder.length()-2, builder.length()).append('>');
//builder.removeFromTheEnd(2).append('>');
}
static String suggestVarName(GrExpression expr, ExpressionContext expressionContext) {
final DefaultGroovyVariableNameValidator nameValidator =
new DefaultGroovyVariableNameValidator(expr, expressionContext.myUsedVarNames, true);
final String[] varNames = GroovyNameSuggestionUtil.suggestVariableNames(expr, nameValidator);
LOG.assertTrue(varNames.length > 0);
expressionContext.myUsedVarNames.add(varNames[0]);
return varNames[0];
}
static String suggestVarName(PsiType type, GroovyPsiElement context, ExpressionContext expressionContext) {
final DefaultGroovyVariableNameValidator nameValidator =
new DefaultGroovyVariableNameValidator(context, expressionContext.myUsedVarNames, true, true);
if (type instanceof PsiPrimitiveType) type = TypesUtil.boxPrimitiveType(type, context.getManager(), context.getResolveScope());
final String[] varNames = GroovyNameSuggestionUtil.suggestVariableNameByType(type, nameValidator);
LOG.assertTrue(varNames.length > 0);
expressionContext.myUsedVarNames.add(varNames[0]);
return varNames[0];
}
public static String validateName(String name, GroovyPsiElement context, ExpressionContext expressionContext) {
return new DefaultGroovyVariableNameValidator(context, expressionContext.myUsedVarNames, true).validateName(name, true);
}
public static void writeCodeReferenceElement(StringBuilder builder, GrCodeReferenceElement referenceElement) {
final GroovyResolveResult resolveResult = referenceElement.advancedResolve();
final PsiElement resolved = resolveResult.getElement();
if (resolved == null) {
builder.append(referenceElement.getText());
return;
}
LOG.assertTrue(resolved instanceof PsiClass || resolved instanceof PsiPackage);
if (resolved instanceof PsiClass) {
builder.append(((PsiClass)resolved).getQualifiedName());
}
else {
builder.append(((PsiPackage)resolved).getQualifiedName());
}
writeTypeParameters(builder, referenceElement.getTypeArguments(), referenceElement, new GeneratorClassNameProvider());
}
public static void invokeMethodByName(@Nullable GrExpression caller,
@NotNull String methodName,
@NotNull GrExpression[] exprs,
@NotNull GrNamedArgument[] namedArgs,
@NotNull GrClosableBlock[] closureArgs,
@NotNull ExpressionGenerator expressionGenerator,
@NotNull GroovyPsiElement psiContext) {
GroovyResolveResult call = resolveMethod(caller, methodName, exprs, namedArgs, closureArgs, psiContext);
invokeMethodByResolveResult(caller, call, methodName, exprs, namedArgs, closureArgs, expressionGenerator, psiContext);
}
@NotNull
public static GroovyResolveResult resolveMethod(@Nullable GrExpression caller,
@NotNull String methodName,
@NotNull GrExpression[] exprs,
@NotNull GrNamedArgument[] namedArgs,
@NotNull GrClosableBlock[] closureArgs,
@NotNull GroovyPsiElement psiContext) {
GroovyResolveResult call = GroovyResolveResult.EMPTY_RESULT;
final PsiType type;
if (caller == null) {
type = GroovyPsiElementFactory.getInstance(psiContext.getProject()).createExpressionFromText("this", psiContext).getType();
}
else {
type = caller.getType();
}
if (type != null) {
final PsiType[] argumentTypes = PsiUtil.getArgumentTypes(namedArgs, exprs, closureArgs, false, null, false);
final GroovyResolveResult[] candidates = ResolveUtil.getMethodCandidates(type, methodName, psiContext, argumentTypes);
call = PsiImplUtil.extractUniqueResult(candidates);
}
return call;
}
public static void invokeMethodByResolveResult(@Nullable GrExpression caller,
@NotNull GroovyResolveResult resolveResult,
@NotNull String methodName,
@NotNull GrExpression[] exprs,
@NotNull GrNamedArgument[] namedArgs,
@NotNull GrClosableBlock[] closureArgs,
@NotNull ExpressionGenerator expressionGenerator,
@NotNull GroovyPsiElement psiContext) {
final PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiMethod) {
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
expressionGenerator.invokeMethodOn(((PsiMethod)resolved), caller, exprs, namedArgs, closureArgs, substitutor, psiContext);
return;
}
//other case
final StringBuilder builder = expressionGenerator.getBuilder();
final ExpressionContext expressionContext = expressionGenerator.getContext();
if (caller != null) {
caller.accept(expressionGenerator);
builder.append('.');
}
builder.append(methodName);
final ArgumentListGenerator argumentListGenerator = new ArgumentListGenerator(builder, expressionContext);
argumentListGenerator.generate(null, exprs, namedArgs, closureArgs, psiContext);
}
static void writeStatement(@NotNull StringBuilder codeBlockBuilder,
@NotNull StringBuilder statementBuilder,
@Nullable GrStatement statement,
@Nullable ExpressionContext context) {
final PsiElement parent = statement == null ? null : statement.getParent();
final boolean addParentheses;
if (statement == null) {
addParentheses = context != null && context.shouldInsertCurlyBrackets();
}
else {
addParentheses =
context != null && (context.shouldInsertCurlyBrackets() || !context.myStatements.isEmpty()) && parent instanceof GrControlStatement;
}
if (addParentheses) {
codeBlockBuilder.append("{\n");
}
if (context != null) {
insertStatementFromContextBefore(codeBlockBuilder, context);
}
codeBlockBuilder.append(statementBuilder);
if (addParentheses) {
codeBlockBuilder.append("}\n");
}
}
public static void insertStatementFromContextBefore(StringBuilder codeBlockBuilder, ExpressionContext context) {
for (String st : context.myStatements) {
codeBlockBuilder.append(st).append('\n');
}
}
public static void writeStatement(@NotNull StringBuilder builder, @NotNull ExpressionContext context, @Nullable GrStatement statement, @NotNull StatementWriter writer) {
StringBuilder statementBuilder = new StringBuilder();
ExpressionContext statementContext = context.copy();
writer.writeStatement(statementBuilder, statementContext);
writeStatement(builder, statementBuilder, statement, statementContext);
}
@Nullable
static PsiClass findAccessibleSuperClass(@NotNull PsiElement context, @NotNull PsiClass initialClass) {
Set<PsiClass> visitedClasses = new HashSet<PsiClass>();
PsiClass curClass = initialClass;
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(context.getProject()).getResolveHelper();
while (curClass != null && !resolveHelper.isAccessible(curClass, context, null)) {
curClass = curClass.getSuperClass();
if (visitedClasses.contains(curClass)) return null;
visitedClasses.add(curClass);
}
return curClass;
}
static void writeTypeParameters(StringBuilder text,
PsiTypeParameterListOwner typeParameterListOwner,
final ClassNameProvider classNameProvider) {
if (!typeParameterListOwner.hasTypeParameters()) return;
text.append('<');
PsiTypeParameter[] parameters = typeParameterListOwner.getTypeParameters();
final PsiTypeParameterList typeParameterList = typeParameterListOwner.getTypeParameterList();
for (int i = 0; i < parameters.length; i++) {
if (i > 0) text.append(", ");
PsiTypeParameter parameter = parameters[i];
text.append(parameter.getName());
PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
if (extendsListTypes.length > 0) {
text.append(" extends ");
for (int j = 0; j < extendsListTypes.length; j++) {
if (j > 0) text.append(" & ");
TypeWriter.writeType(text, extendsListTypes[j], typeParameterList, classNameProvider);
}
}
}
text.append('>');
}
static void writeParameterList(@NotNull StringBuilder text,
@NotNull PsiParameter[] parameters,
@NotNull final ClassNameProvider classNameProvider,
@Nullable ExpressionContext context) {
Set<String> usedNames = new HashSet<String>();
text.append('(');
//writes myParameters
int i = 0;
while (i < parameters.length) {
PsiParameter parameter = parameters[i];
if (parameter == null) continue;
if (parameter instanceof PsiCompiledElement) {
parameter = (PsiParameter)((PsiCompiledElement)parameter).getMirror();
}
if (i > 0) text.append(", "); //append ','
if (!classNameProvider.forStubs()) {
ModifierListGenerator.writeModifiers(text, parameter.getModifierList(), ModifierListGenerator.JAVA_MODIFIERS, true);
}
if (context != null) {
if (context.analyzedVars.toMakeFinal(parameter) && !parameter.hasModifierProperty(PsiModifier.FINAL)) {
text.append(PsiModifier.FINAL).append(' ');
}
TypeWriter.writeType(text, context.typeProvider.getParameterType(parameter), parameter, classNameProvider);
}
else {
TypeWriter.writeType(text, parameter.getType(), parameter, classNameProvider);
}
text.append(' ');
text.append(generateUniqueName(usedNames, parameter.getName()));
i++;
}
text.append(')');
text.append(' ');
}
private static String generateUniqueName(Set<String> usedNames, String name) {
if (StringUtil.isEmptyOrSpaces(name)) {
name = "p";
}
while (!usedNames.add(name)) {
name += "x";
}
return name;
}
static void writeThrowsList(StringBuilder text,
PsiReferenceList throwsList,
PsiClassType[] exceptions,
final ClassNameProvider classNameProvider) {
if (exceptions.length <= 0) return;
text.append("throws ");
for (int i = 0; i < exceptions.length; i++) {
PsiClassType exception = exceptions[i];
if (i != 0) {
text.append(',');
}
TypeWriter.writeType(text, exception, throwsList, classNameProvider);
text.append(' ');
}
}
static Set<String> getVarTypes(GrVariableDeclaration variableDeclaration) {
GrVariable[] variables = variableDeclaration.getVariables();
final GrTypeElement typeElement = variableDeclaration.getTypeElementGroovy();
Set<String> types = new HashSet<String>(variables.length);
if (typeElement == null) {
if (variables.length > 1) {
for (GrVariable variable : variables) {
final GrExpression initializer = variable.getInitializerGroovy();
if (initializer != null) {
final PsiType varType = initializer.getType();
if (varType != null) {
types.add(getTypeText(varType, variableDeclaration));
}
}
}
}
}
return types;
}
static String getTypeText(PsiType varType, PsiElement context) {
final StringBuilder builder = new StringBuilder();
TypeWriter.writeType(builder, varType, context);
return builder.toString();
}
static ArrayList<GrParameter> getActualParams(GrMethod constructor, int skipOptional) {
GrParameter[] parameterList = constructor.getParameters();
return getActualParams(parameterList, skipOptional);
}
public static ArrayList<GrParameter> getActualParams(GrParameter[] parameters, int skipOptional) {
final ArrayList<GrParameter> actual = new ArrayList<GrParameter>(Arrays.asList(parameters));
if (skipOptional == 0) return actual;
for (int i = parameters.length - 1; i >= 0; i--) {
if (!actual.get(i).isOptional()) continue;
actual.remove(i);
skipOptional--;
if (skipOptional == 0) break;
}
return actual;
}
public static void writeSimpleVarDeclaration(GrVariableDeclaration variableDeclaration,
StringBuilder builder,
ExpressionContext expressionContext) {
GrVariable[] variables = variableDeclaration.getVariables();
//Set<String> types = getVarTypes(variableDeclaration);
//if (types.size() > 1) {
if (variables.length > 1 && variableDeclaration.getParent() instanceof GrControlStatement) {
expressionContext.setInsertCurlyBrackets();
}
for (GrVariable variable : variables) {
writeVariableSeparately(variable, builder, expressionContext);
builder.append(";\n");
}
builder.delete(builder.length()-1, builder.length());
//builder.removeFromTheEnd(1);
/*return;
}
ModifierListGenerator.writeModifiers(builder, variableDeclaration.getModifierList());
PsiType type = getVarType(variables[0]);
writeType(builder, type, variableDeclaration);
builder.append(" ");
for (GrVariable variable : variables) {
writeVariableWithoutType(builder, expressionContext, variable);
builder.append(", ");
}
if (variables.length > 0) {
builder.delete(builder.length() - 2, builder.length());
}
builder.append(";");*/
}
static void writeVariableWithoutType(StringBuilder builder,
ExpressionContext expressionContext,
GrVariable variable,
boolean wrapped,
PsiType original) {
builder.append(variable.getName());
final GrExpression initializer = variable.getInitializerGroovy();
if (initializer != null) {
builder.append(" = ");
if (wrapped) {
builder.append("new ").append(GroovyCommonClassNames.GROOVY_LANG_REFERENCE);
if (original != null) {
builder.append('<');
TypeWriter.writeType(builder, original, variable, new GeneratorClassNameProvider());
builder.append('>');
}
builder.append('(');
}
final PsiType iType = getDeclaredType(initializer, expressionContext);
//generate cast
if (original != null && iType != null && !TypesUtil.isAssignable(original, iType, initializer)) {
builder.append('(');
TypeWriter.writeType(builder, original, initializer);
builder.append(')');
}
initializer.accept(new ExpressionGenerator(builder, expressionContext));
if (wrapped) {
builder.append(')');
}
}
}
static void writeVariableSeparately(GrVariable variable, StringBuilder builder, ExpressionContext expressionContext) {
PsiType type = expressionContext.typeProvider.getVarType(variable);
ModifierListGenerator.writeModifiers(builder, variable.getModifierList());
PsiType originalType = type;
LocalVarAnalyzer.Result analyzedVars = expressionContext.analyzedVars;
boolean wrapped = false;
if (analyzedVars != null) {
if (analyzedVars.toMakeFinal(variable) && !variable.hasModifierProperty(PsiModifier.FINAL)) {
builder.append(PsiModifier.FINAL).append(' ');
}
else if (analyzedVars.toWrap(variable)) {
builder.append(PsiModifier.FINAL).append(' ');
type = JavaPsiFacade.getElementFactory(expressionContext.project).createTypeFromText(
GroovyCommonClassNames.GROOVY_LANG_REFERENCE + "<" + getTypeText(originalType, variable) + ">", variable);
wrapped = true;
}
}
TypeWriter.writeType(builder, type, variable);
builder.append(' ');
writeVariableWithoutType(builder, expressionContext, variable, wrapped, originalType);
}
private static final Map<IElementType, Pair<String, IElementType>> binOpTypes = new HashMap<IElementType, Pair<String, IElementType>>();
static {
binOpTypes.put(GroovyTokenTypes.mPLUS_ASSIGN, Pair.create("+", GroovyTokenTypes.mPLUS));
binOpTypes.put(GroovyTokenTypes.mMINUS_ASSIGN, Pair.create("-", GroovyTokenTypes.mMINUS));
binOpTypes.put(GroovyTokenTypes.mSTAR_ASSIGN, Pair.create("*", GroovyTokenTypes.mSTAR));
binOpTypes.put(GroovyTokenTypes.mDIV_ASSIGN, Pair.create("/", GroovyTokenTypes.mDIV));
binOpTypes.put(GroovyTokenTypes.mMOD_ASSIGN, Pair.create("%", GroovyTokenTypes.mMOD));
binOpTypes.put(GroovyTokenTypes.mSL_ASSIGN, new Pair<String, IElementType>("<<", GroovyElementTypes.COMPOSITE_LSHIFT_SIGN));
binOpTypes.put(GroovyTokenTypes.mSR_ASSIGN, new Pair<String, IElementType>(">>", GroovyElementTypes.COMPOSITE_RSHIFT_SIGN));
binOpTypes.put(GroovyTokenTypes.mBSR_ASSIGN, new Pair<String, IElementType>(">>>", GroovyElementTypes.COMPOSITE_TRIPLE_SHIFT_SIGN));
binOpTypes.put(GroovyTokenTypes.mBAND_ASSIGN, Pair.create("&", GroovyTokenTypes.mBAND));
binOpTypes.put(GroovyTokenTypes.mBOR_ASSIGN, Pair.create("|", GroovyTokenTypes.mBOR));
binOpTypes.put(GroovyTokenTypes.mBXOR_ASSIGN, Pair.create("^", GroovyTokenTypes.mBXOR));
binOpTypes.put(GroovyTokenTypes.mSTAR_STAR_ASSIGN, Pair.create("**", GroovyTokenTypes.mSTAR_STAR));
}
public static Pair<String, IElementType> getBinaryOperatorType(IElementType op_assign) {
return binOpTypes.get(op_assign);
}
public static String suggestMethodName(GroovyPsiElement place, String initialName, ExpressionContext context) {
int count = 0;
String name = initialName;
Class[] classes = {PsiMethod.class};
final Map<PsiMethod, String> setters = context.getSetters();
while (setters.containsValue(name) || ResolveUtil.resolveExistingElement(
place,
new MethodResolverProcessor(name, place, false, null, null, null, true, true),
classes) != null) {
name = initialName + count;
count++;
}
return name;
}
public static boolean isCastNeeded(@NotNull GrExpression qualifier, @NotNull final PsiMember member, ExpressionContext context) {
PsiType declared = getDeclaredType(qualifier, context);
if (declared == null) return false;
final CheckProcessElement checker = new CheckProcessElement(member);
ResolveUtil.processAllDeclarationsSeparately(declared, checker, new BaseScopeProcessor() {
@Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
return false;
}
}, ResolveState.initial(), qualifier);
return !checker.isFound();
}
static class CheckProcessElement implements PsiScopeProcessor {
private final PsiElement myMember;
private final PsiManager myManager;
private boolean myResult = false;
public CheckProcessElement(@NotNull PsiElement member) {
myMember = member;
myManager = member.getManager();
}
@Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
if (myManager.areElementsEquivalent(element, myMember)) {
myResult = true;
return false;
}
return true;
}
@Override
public <T> T getHint(@NotNull Key<T> hintKey) {
return null;
}
@Override
public void handleEvent(@NotNull Event event, Object associated) {
}
public boolean isFound() {
return myResult;
}
}
@Nullable
public static PsiType getDeclaredType(@Nullable GrExpression expression, ExpressionContext context) {
if (expression instanceof GrReferenceExpression) {
final GroovyResolveResult resolveResult = ((GrReferenceExpression)expression).advancedResolve();
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiVariable) {
return substitutor.substitute(context.typeProvider.getVarType((PsiVariable)resolved));
}
else if (resolved instanceof PsiMethod) {
return getDeclaredType((PsiMethod)resolved, substitutor, context);
}
}
else if (expression instanceof GrMethodCall) {
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) {
return getDeclaredType((PsiMethod)result.getElement(), result.getSubstitutor(), context);
}
}
else if (expression instanceof GrAssignmentExpression) {
return getDeclaredType(((GrAssignmentExpression)expression).getRValue(), context);
}
else if (expression instanceof GrConditionalExpression) {
return TypesUtil.getLeastUpperBoundNullable(getDeclaredType(((GrConditionalExpression)expression).getThenBranch(), context),
getDeclaredType(((GrConditionalExpression)expression).getElseBranch(), context),
expression.getManager());
}
else if (expression instanceof GrParenthesizedExpression) {
return getDeclaredType(((GrParenthesizedExpression)expression).getOperand(), context);
}
else if (expression == null) {
return null;
}
return expression.getType();
}
public static PsiType getDeclaredType(PsiMethod method, PsiSubstitutor substitutor, ExpressionContext context) {
if (method instanceof GrGdkMethod) method = ((GrGdkMethod)method).getStaticMethod();
if (context.isClassConverted(method.getContainingClass())) {
return substitutor.substitute(PsiUtil.getSmartReturnType(method));
}
else {
return substitutor.substitute(method.getReturnType());
}
}
public static void wrapInCastIfNeeded(StringBuilder builder,
@NotNull PsiType expected,
@Nullable PsiType actual,
GroovyPsiElement context,
ExpressionContext expressionContext,
StatementWriter writer) {
if (actual != null && TypesUtil.isAssignable(expected, actual, context) || expected.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
writer.writeStatement(builder, expressionContext);
}
else {
wrapInCast(builder, expected, context, expressionContext, writer);
}
}
private static void wrapInCast(StringBuilder builder,
@NotNull PsiType expected,
PsiElement context,
ExpressionContext expressionContext,
StatementWriter writer) {
builder.append("((");
//todo check operator priority IDEA-93790
TypeWriter.writeType(builder, expected, context);
builder.append(")(") ;
writer.writeStatement(builder, expressionContext);
builder.append("))");
}
static PsiType getNotNullType(PsiElement context, PsiType type) {
return type != null ? type : TypesUtil.getJavaLangObject(context);
}
public static void writeThisReference(@Nullable PsiClass targetClass, StringBuilder buffer, ExpressionContext context) {
if (targetClass != null && !(targetClass instanceof PsiAnonymousClass)) {
final GrCodeReferenceElement ref = GroovyPsiElementFactory.getInstance(context.project).createCodeReferenceElementFromClass(targetClass);
writeCodeReferenceElement(buffer, ref);
buffer.append('.');
}
buffer.append("this");
}
public static void writeSuperReference(@Nullable PsiClass targetClass, StringBuilder buffer, ExpressionContext context) {
if (targetClass != null && !(targetClass instanceof PsiAnonymousClass)) {
final GrCodeReferenceElement ref = GroovyPsiElementFactory.getInstance(context.project).createCodeReferenceElementFromClass(targetClass);
writeCodeReferenceElement(buffer, ref);
buffer.append('.');
}
buffer.append("super");
}
@Nullable
static PsiElement getWrappingImplicitClass(@NotNull PsiElement place) {
PsiElement parent = place.getParent();
while (parent != null) {
if (parent instanceof PsiClass) return null;
if (parent instanceof GroovyFile && !(PsiUtil.isInDummyFile(parent))) return null;
if (parent instanceof GrClosableBlock) return parent;
parent = parent.getContext();
}
return null;
}
static void writeDocComment(StringBuilder buffer, PsiMember member, boolean addLineFeed) {
if (member instanceof PsiDocCommentOwner) {
final PsiDocComment comment = ((PsiDocCommentOwner)member).getDocComment();
if (comment != null) {
final String text = comment.getText();
buffer.append(text);
if (addLineFeed) buffer.append('\n');
}
}
}
}