diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertConcatenationToGstringIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertConcatenationToGstringIntention.java index 18e265d4e31c..218e1f5bab7b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertConcatenationToGstringIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertConcatenationToGstringIntention.java @@ -156,8 +156,8 @@ public class ConvertConcatenationToGstringIntention extends Intention { final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject()); final PsiClassType stringType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, element.getResolveScope()); - final PsiClassType gstringType = factory.createTypeByFQClassName("groovy.lang.GString", element.getResolveScope()); - if (!TypeConversionUtil.isAssignable(stringType, type) && !TypeConversionUtil.isAssignable(gstringType, type)) return false; + final PsiClassType gstringType = factory.createTypeByFQClassName(GrStringUtil.GROOVY_LANG_GSTRING, element.getResolveScope()); + if (!(TypeConversionUtil.isAssignable(stringType, type) || TypeConversionUtil.isAssignable(gstringType, type))) return false; return true; } 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 9b44903b31e8..8236677b71f3 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 @@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; import org.jetbrains.plugins.groovy.lang.psi.impl.GrTupleType; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor; @@ -67,7 +68,17 @@ public class TypesUtil { return JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory().createTypeByFQClassName(qName, scope); } - return getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{rType}); + final PsiType type = getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{rType}); + if (type != null) { + return type; + } + + if (rType.equalsToText(GrStringUtil.GROOVY_LANG_GSTRING)) { + PsiType gstringType = JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory() + .createTypeByFQClassName(GrStringUtil.GROOVY_LANG_GSTRING, binaryExpression.getResolveScope()); + return getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{gstringType}); + } + return null; } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java index a88e4fdaba78..6c0d3ba11a96 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic; import com.intellij.lang.ASTNode; +import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiType; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; @@ -24,6 +25,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; /** * @author ilyas @@ -42,14 +44,22 @@ public class GrAdditiveExpressionImpl extends GrBinaryExpressionImpl { IElementType tokenType = getOperationTokenType(); if (tokenType == GroovyTokenTypes.mPLUS) { - if (lType != null && lType.equalsToText("java.lang.String")) { - return getTypeByFQName("java.lang.String"); + if (isStringType(lType)) { + return getTypeByFQName(CommonClassNames.JAVA_LANG_STRING); + } + final GrExpression rop = getRightOperand(); + if (rop != null && isStringType(rop.getType())) { + return getTypeByFQName(CommonClassNames.JAVA_LANG_STRING); } } return null; } + private static boolean isStringType(PsiType type) { + return type != null && (type.equalsToText(CommonClassNames.JAVA_LANG_STRING) || type.equalsToText(GrStringUtil.GROOVY_LANG_GSTRING)); + } + public String toString() { return "Additive expression"; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java index 65044117ebd4..f1f8440e0769 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrStringImpl.java @@ -17,12 +17,14 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals; import com.intellij.lang.ASTNode; +import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; /** * @author ilyas @@ -38,7 +40,12 @@ public class GrStringImpl extends GrExpressionImpl implements GrString { } public PsiType getType() { - return getTypeByFQName("java.lang.String"); + if (findChildByClass(GrStringInjection.class) != null) { + return getTypeByFQName(GrStringUtil.GROOVY_LANG_GSTRING); + } + else { + return getTypeByFQName(CommonClassNames.JAVA_LANG_STRING); + } } public boolean isPlainString() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java index 3fa3e885f47d..7660636bf087 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java @@ -22,6 +22,7 @@ public class GrStringUtil { private static final String QUOTE = "'"; private static final String DOUBLE_QUOTES = "\""; private static final String TRIPLE_DOUBLE_QUOTES = "\"\"\""; + public static final String GROOVY_LANG_GSTRING = "groovy.lang.GString"; private GrStringUtil() { } @@ -141,6 +142,7 @@ public class GrStringUtil { * @param literal * @return */ + //todo use this code public static GrString replaceStringInjectionByLiteral(PsiElement injection, GrLiteral literal) { if (injection.getParent() instanceof GrClosableBlock) { injection = injection.getParent(); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCompletionTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCompletionTest.java index de366bdd7627..7a5446ed8d86 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCompletionTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyCompletionTest.java @@ -137,7 +137,7 @@ public class GroovyCompletionTest extends LightCodeInsightFixtureTestCase { doVariantableTest("abx", "aby"); } - public void testNamedParametersForNotMap() throws Throwable { + public void testNamedParametersForNotMap() throws Throwable { doBasicTest(); } @@ -202,7 +202,7 @@ public class GroovyCompletionTest extends LightCodeInsightFixtureTestCase { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "xx", "xy"); } - public void testInnerClassExtendsImplementsCompletion()throws Throwable{ + public void testInnerClassExtendsImplementsCompletion() throws Throwable { myFixture.testCompletionVariants(getTestName(false) + ".groovy", "extends", "implements"); } @@ -226,7 +226,7 @@ public class GroovyCompletionTest extends LightCodeInsightFixtureTestCase { public void testThisKeywordCompletionAfterClassName1() throws Throwable { doBasicTest(); } - + public void testThisKeywordCompletionAfterClassName2() throws Throwable { doBasicTest(); } @@ -254,9 +254,13 @@ public class GroovyCompletionTest extends LightCodeInsightFixtureTestCase { public void testTypeCompletionInVariableDeclaration2() throws Throwable { doBasicTest(); } + public void testTypeCompletionInParameter() throws Throwable { doBasicTest(); } + public void testGStringConcatenationCompletion() throws Throwable { + myFixture.testCompletionVariants(getTestName(false) + ".groovy", "substring", "substring", "subSequence"); + } } diff --git a/plugins/groovy/testdata/groovy/completion/GStringCompletion.groovy b/plugins/groovy/testdata/groovy/completion/GStringCompletion.groovy new file mode 100644 index 000000000000..f4f09c9c2fed --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/GStringCompletion.groovy @@ -0,0 +1 @@ +"ab${2}".getV \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/completion/GStringConcatenationCompletion.groovy b/plugins/groovy/testdata/groovy/completion/GStringConcatenationCompletion.groovy new file mode 100644 index 000000000000..a48173fd58d9 --- /dev/null +++ b/plugins/groovy/testdata/groovy/completion/GStringConcatenationCompletion.groovy @@ -0,0 +1 @@ +(2+"ab${2}").sub \ No newline at end of file