convert simple reference expressions

This commit is contained in:
Maxim Medvedev
2011-04-15 16:00:26 +04:00
parent 09492d3516
commit 8daf5892fc
8 changed files with 155 additions and 47 deletions
@@ -73,13 +73,16 @@ public class CodeBlockGenerator extends Generator {
@Override
public void visitOpenBlock(GrOpenBlock block) {
builder.append("{\n");
super.visitOpenBlock(block);
final GrStatement[] statements = block.getStatements();
for (GrStatement statement : statements) {
statement.accept(this);
builder.append('\n');
}
builder.append("}\n");
}
@Override
public void visitStatement(GrStatement statement) {
super.visitStatement(statement); //To change body of overridden methods use File | Settings | File Templates.
LOG.assertTrue(false, "all statements must be overloaded");
}
@Override
@@ -191,6 +194,7 @@ public class CodeBlockGenerator extends Generator {
@Override
public void visitForStatement(GrForStatement forStatement) {
final StringBuilder builder = new StringBuilder();
builder.append("for(");
final GrForClause clause = forStatement.getClause();
ExpressionContext forContext = context.extend();
@@ -199,16 +203,14 @@ public class CodeBlockGenerator extends Generator {
final GrVariable declaredVariable = clause.getDeclaredVariable();
LOG.assertTrue(declaredVariable != null);
builder.append("for(");
writeVariableWithoutSemicolonAndInitializer(builder, declaredVariable);
builder.append(" : ");
if (expression != null) {
final ExpressionContext context = forContext.copy();
expression.accept(new ExpressionGenerator(builder, context));
}
builder.append(")");
}
else {
else if (clause instanceof GrTraditionalForClause) {
final GrTraditionalForClause cl = (GrTraditionalForClause)clause;
final GrCondition initialization = cl.getInitialization();
final GrExpression condition = cl.getCondition();
@@ -244,10 +246,13 @@ public class CodeBlockGenerator extends Generator {
if (update != null) {
genForPart(builder, update, forContext.copy());
}
builder.append(")");
}
builder.append(")");
forStatement.getBody().accept(new CodeBlockGenerator(builder, forContext));
final GrStatement body = forStatement.getBody();
if (body != null) {
body.accept(new CodeBlockGenerator(builder, forContext));
}
}
private static void genForPart(StringBuilder builder, GrExpression part, final ExpressionContext context) {
@@ -486,11 +491,6 @@ public class CodeBlockGenerator extends Generator {
}
}
private void writeVariable(GrVariable variable) {
//todo
throw new UnsupportedOperationException();
}
private static String getTypeText(PsiType varType) {
final StringBuilder builder = new StringBuilder();
GenerationUtil.writeType(builder, varType);
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.intentions.conversions.ConvertGStringToStringIntention;
@@ -32,6 +31,7 @@ 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.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
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.GrArgumentLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
@@ -59,6 +59,9 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil.*;
/**
* @author Maxim.Medvedev
@@ -128,7 +131,7 @@ public class ExpressionGenerator extends Generator {
}
}
GenerationUtil.invokeMethodByName(invoked, "call", exprs, namedArgs, clArgs, this, methodCallExpression);
invokeMethodByName(invoked, "call", exprs, namedArgs, clArgs, this, methodCallExpression);
}
@Override
@@ -140,8 +143,8 @@ public class ExpressionGenerator extends Generator {
final String varName;
if (hasFieldInitialization) {
builder = new StringBuilder();
varName = GenerationUtil.suggestVarName(type, newExpression, this.context);
GenerationUtil.writeType(builder, type);
varName = suggestVarName(type, newExpression, this.context);
writeType(builder, type);
builder.append(" ").append(varName).append(" = ");
}
else {
@@ -164,10 +167,10 @@ public class ExpressionGenerator extends Generator {
final PsiType builtIn = typeElement.getType();
LOG.assertTrue(builtIn instanceof PsiPrimitiveType);
final PsiType boxed = TypesUtil.boxPrimitiveType(builtIn, newExpression.getManager(), newExpression.getResolveScope());
GenerationUtil.writeType(builder, boxed);
writeType(builder, boxed);
}
else if (referenceElement != null) {
GenerationUtil.writeCodeReferenceElement(builder, referenceElement);
writeCodeReferenceElement(builder, referenceElement);
}
final GrArgumentList argList = newExpression.getArgumentList();
@@ -259,7 +262,7 @@ public class ExpressionGenerator extends Generator {
private static boolean hasFieldInitialization(GrNewExpression newExpression) {
final GrArgumentList argumentList = newExpression.getArgumentList();
if (argumentList == null) return false;
if (argumentList.getNamedArguments().length > 0) return false;
if (argumentList.getNamedArguments().length == 0) return false;
final GrCodeReferenceElement refElement = newExpression.getReferenceElement();
if (refElement == null) return false;
@@ -275,7 +278,7 @@ public class ExpressionGenerator extends Generator {
}
private void writeTypeBody(StringBuilder builder, GrAnonymousClassDefinition anonymous) {
//todo
//todo write type body for anonymous class
throw new UnsupportedOperationException();
}
@@ -460,6 +463,8 @@ public class ExpressionGenerator extends Generator {
else {
builder.append(value);
}
//todo replace with character in some cases
}
@Override
@@ -471,16 +476,70 @@ public class ExpressionGenerator extends Generator {
@Override
public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
final GrExpression qualifier = referenceExpression.getQualifier();
final PsiElement refNameElement = referenceExpression.getReferenceNameElement();
final GroovyResolveResult resolveResult = referenceExpression.advancedResolve();
LOG.assertTrue(!(referenceExpression.getParent() instanceof GrMethodCall));
if (qualifier != null) {
qualifier.accept(this);
builder.append(".");
final GrExpression qualifier = referenceExpression.getQualifier();
final GroovyResolveResult resolveResult = referenceExpression.advancedResolve();
final PsiElement resolved = resolveResult.getElement();
final IElementType type = referenceExpression.getDotTokenType();
GrExpression qualifierToUse = qualifier;
if (type == GroovyTokenTypes.mOPTIONAL_DOT) {
LOG.assertTrue(qualifier != null);
String qualifierName = createVarByInitializer(qualifier);
builder.append(qualifierName).append(" == null ? null : ");
qualifierToUse = factory.createReferenceExpressionFromText(qualifierName, referenceExpression);
}
builder.append(referenceExpression.getReferenceName());
//todo make reference expression
if (resolveResult.isInvokedOnProperty()) {
LOG.assertTrue(resolved instanceof PsiMethod);
invokeMethodOn(
((PsiMethod)resolved),
qualifierToUse,
GrExpression.EMPTY_ARRAY,
GrNamedArgument.EMPTY_ARRAY,
GrClosableBlock.EMPTY_ARRAY,
resolveResult.getSubstitutor(),
referenceExpression
);
}
else {
if (qualifierToUse != null) {
qualifierToUse.accept(this);
builder.append('.');
}
final String refName =
resolved instanceof PsiNamedElement ? ((PsiNamedElement)resolved).getName() : referenceExpression.getReferenceName();
builder.append(refName);
}
}
private String createVarByInitializer(GrExpression initializer) {
if (initializer instanceof GrReferenceExpression) {
final GrExpression qualifier = ((GrReferenceExpression)initializer).getQualifier();
if (qualifier == null) {
final PsiElement resolved = ((GrReferenceExpression)initializer).resolve();
if (resolved instanceof GrVariable && GroovyRefactoringUtil.isLocalVariable((GrVariable)resolved)) {
//don't create new var. it is already exists
return ((GrVariable)resolved).getName();
}
}
}
final String name = suggestVarName(initializer, context);
final StringBuilder builder = new StringBuilder();
builder.append("final ");
writeType(builder, initializer.getType());
builder.append(' ').append(name).append(" = ");
initializer.accept(new ExpressionGenerator(builder, context));
builder.append(';');
context.myStatements.add(builder.toString());
return name;
}
@Override
@@ -490,14 +549,8 @@ public class ExpressionGenerator extends Generator {
final PsiElement resolved = expr.resolve();
LOG.assertTrue(resolved instanceof PsiClass);
final PsiElement firstContainingClass = PsiTreeUtil.getParentOfType(expr, GrClosableBlock.class, PsiClass.class);
if (expr.getManager().areElementsEquivalent(firstContainingClass, resolved)) {
builder.append(expr.getReferenceName());
}
else {
builder.append(((PsiClass)resolved).getQualifiedName()).append(".").append(expr.getReferenceName());
}
builder.append(((PsiClass)resolved).getQualifiedName()).append(".").append(expr.getReferenceName());
}
@Override
@@ -611,8 +664,8 @@ public class ExpressionGenerator extends Generator {
}
final GroovyResolveResult candidate = PsiImplUtil.getIndexPropertyMethodCandidate(thisType, argTypes, expression);
GenerationUtil.invokeMethodByResolveResult(
selectedExpression, candidate, "getAt", exprArgs, namedArgs, GrClosableBlock.EMPTY_ARRAY, this,expression
invokeMethodByResolveResult(
selectedExpression, candidate, "getAt", exprArgs, namedArgs, GrClosableBlock.EMPTY_ARRAY, this, expression
);
}
@@ -716,10 +769,10 @@ public class ExpressionGenerator extends Generator {
private String generateListOrMapVariableDeclaration(GrListOrMap listOrMap, PsiType type) {
StringBuilder declaration = new StringBuilder();
GenerationUtil.writeType(declaration, type);
final String varName = GenerationUtil.suggestVarName(type, listOrMap, this.context);
writeType(declaration, type);
final String varName = suggestVarName(type, listOrMap, this.context);
declaration.append(" ").append(varName).append(" = new ");
GenerationUtil.writeType(declaration, type);
writeType(declaration, type);
declaration.append("(");
//insert count of elements in list or map
@@ -70,6 +70,16 @@ public class GenerationUtil {
builder.replace(builder.length() - 2, builder.length(), ">");
}
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);
@@ -85,7 +95,20 @@ public class GenerationUtil {
}
public static void writeCodeReferenceElement(StringBuilder builder, GrCodeReferenceElement referenceElement) {
builder.append(referenceElement.getText());
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());
}
public static void invokeMethodByName(GrExpression caller,
@@ -88,4 +88,20 @@ public class CodeBlockGenerationTest extends LightCodeInsightFixtureTestCase {
void _testWhile2() {doTest()}
void _testWhile3() {doTest()}
void testRefExpr() {
myFixture.addFileToProject "Bar.groovy", """
class Bar {
def foo = 2
def getBar() {3}
}
class MyCat {
static getAbc(Bar b) {
return 4
}
}
"""
doTest()
}
}
@@ -0,0 +1,10 @@
print new Bar().foo
print new Bar().bar
def bar = new Bar()
print bar?.foo
def file = new File("")
print file.text
@@ -0,0 +1,6 @@
print(new Bar().getFoo());
print(new Bar().getBar());
Bar bar = new Bar();
print(bar == null ? null : bar.getFoo());
java.io.File file = new java.io.File("");
print(org.codehaus.groovy.runtime.DefaultGroovyMethods.getText(file));
@@ -1,9 +1,9 @@
java.util.Date date = new Date(2011, 4, 9);
if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new Date(20, 11, 23), date)) {
java.util.Date date = new java.util.Date(2011, 4, 9);
if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new java.util.Date(20, 11, 23), date)) {
print("aaa");
print("bbb");
}
else if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new Date(45, 1, 2), date)) {
else if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new java.util.Date(45, 1, 2), date)) {
print("bbb");
}
else print("ccc");
@@ -1,5 +1,5 @@
java.util.Date date = new Date(2011, 4, 9);
if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new Date(20, 11, 23), date)) {
java.util.Date date = new java.util.Date(2011, 4, 9);
if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase(new java.util.Date(20, 11, 23), date)) {
print("aaa");
print("bbb");
}