mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'dany/operator-assignment'
# Conflicts: # plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java
This commit is contained in:
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,4 +51,10 @@ public interface GrReferenceExpression extends GrExpression, GrReferenceElement<
|
||||
|
||||
GrReferenceExpression bindToElementViaStaticImport(@NotNull PsiMember member);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
default PsiType getType() { return getType(false); }
|
||||
|
||||
@Nullable
|
||||
PsiType getType(boolean forceRValue);
|
||||
}
|
||||
|
||||
+16
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -43,6 +43,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrOperatorExpressio
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrBindingVariable;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
@@ -61,7 +62,7 @@ public class GrAssignmentExpressionImpl extends GrOperatorExpressionImpl impleme
|
||||
@Override
|
||||
@NotNull
|
||||
public GrExpression getLValue() {
|
||||
return findExpressionChild(this);
|
||||
return Objects.requireNonNull(findExpressionChild(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,6 +162,16 @@ public class GrAssignmentExpressionImpl extends GrOperatorExpressionImpl impleme
|
||||
return rValue == null ? null : rValue.getType();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
if (TokenSets.ASSIGNMENTS_TO_OPERATORS.containsKey(getOperationTokenType())) {
|
||||
return super.getType();
|
||||
} else {
|
||||
return getRightType();
|
||||
}
|
||||
}
|
||||
|
||||
private static final ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl> RESOLVER = new ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl>() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -177,6 +188,9 @@ public class GrAssignmentExpressionImpl extends GrOperatorExpressionImpl impleme
|
||||
*/
|
||||
lType = ((GrIndexProperty)lValue).getGetterType();
|
||||
}
|
||||
else if (lValue instanceof GrReferenceExpression) {
|
||||
lType = ((GrReferenceExpression)lValue).getType(true);
|
||||
}
|
||||
else {
|
||||
lType = lValue.getType();
|
||||
}
|
||||
|
||||
+126
-90
@@ -18,15 +18,15 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache.PolyVariantResolver;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.profiling.ResolveProfiler;
|
||||
@@ -60,6 +60,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.processors.GroovyResolverProces
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -72,6 +73,14 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
super(node);
|
||||
}
|
||||
|
||||
private final NotNullLazyValue<GrReferenceExpressionReference> myFakeGetterReference = AtomicNotNullLazyValue.createValue(
|
||||
() -> new GrReferenceExpressionReference(this, true)
|
||||
);
|
||||
|
||||
private final NotNullLazyValue<GrReferenceExpressionReference> myFakeReference = AtomicNotNullLazyValue.createValue(
|
||||
() -> new GrReferenceExpressionReference(this, false)
|
||||
);
|
||||
|
||||
@NotNull
|
||||
private static List<GroovyResolveResult> filterMembersFromSuperClasses(GroovyResolveResult[] results) {
|
||||
List<GroovyResolveResult> filtered = new ArrayList<>();
|
||||
@@ -97,7 +106,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] getCallVariants(@Nullable GrExpression upToArgument) {
|
||||
return _resolve(false, true, upToArgument);
|
||||
return _resolve(false, false, true, upToArgument);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -195,19 +204,16 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return "Reference expression";
|
||||
}
|
||||
|
||||
private static final PolyVariantResolver<GrReferenceExpressionImpl> POLY_RESOLVER = new PolyVariantResolver<GrReferenceExpressionImpl>() {
|
||||
@Override
|
||||
@NotNull
|
||||
public GroovyResolveResult[] resolve(@NotNull final GrReferenceExpressionImpl refExpr, final boolean incompleteCode) {
|
||||
return refExpr.doPolyResolve(incompleteCode);
|
||||
}
|
||||
};
|
||||
private static final OurTypesCalculator TYPES_CALCULATOR = new OurTypesCalculator();
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiType getNominalType() {
|
||||
final GroovyResolveResult resolveResult = advancedResolve();
|
||||
return getNominalType(false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiType getNominalType(boolean forceRValue) {
|
||||
final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(multiResolve(false, forceRValue));
|
||||
PsiElement resolved = resolveResult.getElement();
|
||||
|
||||
for (GrReferenceTypeEnhancer enhancer : GrReferenceTypeEnhancer.EP_NAME.getExtensions()) {
|
||||
@@ -361,72 +367,69 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class OurTypesCalculator implements Function<GrReferenceExpressionImpl, PsiType> {
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiType fun(GrReferenceExpressionImpl refExpr) {
|
||||
final PsiElement resolved = refExpr.resolve();
|
||||
@Nullable
|
||||
private static PsiType calculate(@NotNull GrReferenceExpressionImpl refExpr, boolean forceRValue) {
|
||||
final GroovyResolveResult[] results = refExpr.multiResolve(false, forceRValue);
|
||||
final GroovyResolveResult result = PsiImplUtil.extractUniqueResult(results);
|
||||
final PsiElement resolved = result.getElement();
|
||||
|
||||
for (GrExpressionTypeCalculator calculator : GrExpressionTypeCalculator.EP_NAME.getExtensions()) {
|
||||
PsiType type = calculator.calculateType(refExpr, resolved);
|
||||
if (type != null) return type;
|
||||
for (GrExpressionTypeCalculator calculator : GrExpressionTypeCalculator.EP_NAME.getExtensions()) {
|
||||
PsiType type = calculator.calculateType(refExpr, resolved);
|
||||
if (type != null) return type;
|
||||
}
|
||||
|
||||
if (ResolveUtil.isClassReference(refExpr)) {
|
||||
GrExpression qualifier = refExpr.getQualifier();
|
||||
LOG.assertTrue(qualifier != null);
|
||||
return qualifier.getType();
|
||||
}
|
||||
|
||||
if (PsiUtil.isCompileStatic(refExpr)) {
|
||||
final PsiType type;
|
||||
if (resolved instanceof GrField) {
|
||||
type = ((GrField)resolved).getType();
|
||||
}
|
||||
|
||||
if (ResolveUtil.isClassReference(refExpr)) {
|
||||
GrExpression qualifier = refExpr.getQualifier();
|
||||
LOG.assertTrue(qualifier != null);
|
||||
return qualifier.getType();
|
||||
else if (resolved instanceof GrVariable) {
|
||||
type = ((GrVariable)resolved).getDeclaredType();
|
||||
}
|
||||
else if (resolved instanceof GrAccessorMethod) {
|
||||
type = ((GrAccessorMethod)resolved).getProperty().getType();
|
||||
}
|
||||
else {
|
||||
type = null;
|
||||
}
|
||||
if (type != null) {
|
||||
return result.getSubstitutor().substitute(type);
|
||||
}
|
||||
}
|
||||
|
||||
if (PsiUtil.isCompileStatic(refExpr)) {
|
||||
final GroovyResolveResult resolveResult = refExpr.advancedResolve();
|
||||
final PsiElement resolvedF = resolveResult.getElement();
|
||||
final PsiType type;
|
||||
if (resolvedF instanceof GrField) {
|
||||
type = ((GrField)resolvedF).getType();
|
||||
}
|
||||
else if (resolvedF instanceof GrVariable) {
|
||||
type = ((GrVariable)resolvedF).getDeclaredType();
|
||||
}
|
||||
else if (resolvedF instanceof GrAccessorMethod) {
|
||||
type = ((GrAccessorMethod)resolvedF).getProperty().getType();
|
||||
}
|
||||
else {
|
||||
type = null;
|
||||
}
|
||||
if (type != null) {
|
||||
return resolveResult.getSubstitutor().substitute(type);
|
||||
final PsiType nominal = refExpr.getNominalType(forceRValue);
|
||||
|
||||
Boolean reassigned = GrReassignedLocalVarsChecker.isReassignedVar(refExpr);
|
||||
if (reassigned != null && reassigned.booleanValue()) {
|
||||
return GrReassignedLocalVarsChecker.getReassignedVarType(refExpr, true);
|
||||
}
|
||||
|
||||
final PsiType inferred = getInferredTypes(refExpr, resolved);
|
||||
if (inferred == null) {
|
||||
if (nominal == null) {
|
||||
//inside nested closure we could still try to infer from variable initializer. Not sound, but makes sense
|
||||
if (resolved instanceof GrVariable) {
|
||||
LOG.assertTrue(resolved.isValid());
|
||||
return ((GrVariable)resolved).getTypeGroovy();
|
||||
}
|
||||
}
|
||||
|
||||
final PsiType nominal = refExpr.getNominalType();
|
||||
|
||||
Boolean reassigned = GrReassignedLocalVarsChecker.isReassignedVar(refExpr);
|
||||
if (reassigned != null && reassigned.booleanValue()) {
|
||||
return GrReassignedLocalVarsChecker.getReassignedVarType(refExpr, true);
|
||||
}
|
||||
|
||||
final PsiType inferred = getInferredTypes(refExpr, resolved);
|
||||
if (inferred == null) {
|
||||
if (nominal == null) {
|
||||
//inside nested closure we could still try to infer from variable initializer. Not sound, but makes sense
|
||||
if (resolved instanceof GrVariable) {
|
||||
LOG.assertTrue(resolved.isValid());
|
||||
return ((GrVariable)resolved).getTypeGroovy();
|
||||
}
|
||||
}
|
||||
return nominal;
|
||||
}
|
||||
|
||||
if (nominal == null) return inferred;
|
||||
if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
|
||||
if (resolved instanceof GrVariable && ((GrVariable)resolved).getTypeElementGroovy() != null) {
|
||||
return nominal;
|
||||
}
|
||||
|
||||
if (nominal == null) return inferred;
|
||||
if (!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(nominal), inferred, false)) {
|
||||
if (resolved instanceof GrVariable && ((GrVariable)resolved).getTypeElementGroovy() != null) {
|
||||
return nominal;
|
||||
}
|
||||
}
|
||||
return inferred;
|
||||
}
|
||||
return inferred;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -450,9 +453,17 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPES_CALCULATOR);
|
||||
public PsiType getType(boolean forceRValue) {
|
||||
if (forceRValue) {
|
||||
return calculate(this, true);
|
||||
}
|
||||
else {
|
||||
return TypeInferenceHelper.getCurrentContext().getExpressionType(
|
||||
this, e -> calculate(e, false)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -461,7 +472,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GroovyResolveResult[] doPolyResolve(boolean incompleteCode) {
|
||||
GroovyResolveResult[] doPolyResolve(boolean incompleteCode, boolean forceRValue) {
|
||||
final PsiElement nameElement = getReferenceNameElement();
|
||||
final String name = getReferenceName();
|
||||
if (name == null || nameElement == null) return GroovyResolveResult.EMPTY_ARRAY;
|
||||
@@ -482,7 +493,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
}
|
||||
|
||||
final GroovyResolveResult[] results = _resolve(incompleteCode, false, null);
|
||||
final GroovyResolveResult[] results = _resolve(forceRValue, incompleteCode, false, null);
|
||||
if (results.length == 0) {
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
@@ -507,8 +518,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GroovyResolveResult[] _resolve(boolean incomplete, boolean allVariants, @Nullable GrExpression upToArgument) {
|
||||
private GroovyResolveResult[] _resolve(boolean forceRValue,
|
||||
boolean incomplete,
|
||||
boolean allVariants,
|
||||
@Nullable GrExpression upToArgument) {
|
||||
final GroovyResolverProcessor processor = GroovyResolverProcessorBuilder.builder()
|
||||
.setForceRValue(forceRValue)
|
||||
.setIncomplete(incomplete)
|
||||
.setAllVariants(allVariants)
|
||||
.setUpToArgument(upToArgument)
|
||||
@@ -535,22 +550,28 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
|
||||
@Override
|
||||
public boolean isReferenceTo(PsiElement element) {
|
||||
PsiElement baseTarget = resolve();
|
||||
if (getManager().areElementsEquivalent(element, baseTarget)) {
|
||||
return true;
|
||||
}
|
||||
GroovyResolveResult[] results = multiResolve(false);
|
||||
|
||||
PsiElement target = GroovyTargetElementEvaluator.correctSearchTargets(baseTarget);
|
||||
if (target != baseTarget && getManager().areElementsEquivalent(element, target)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element instanceof PsiMethod && target instanceof PsiMethod) {
|
||||
PsiMethod[] superMethods = ((PsiMethod)target).findSuperMethods(false);
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if (Arrays.asList(superMethods).contains(element)) {
|
||||
for (GroovyResolveResult result : results) {
|
||||
if (!result.isValidResult()) continue;
|
||||
PsiElement baseTarget = result.getElement();
|
||||
if (baseTarget == null) continue;
|
||||
if (getManager().areElementsEquivalent(element, baseTarget)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PsiElement target = GroovyTargetElementEvaluator.correctSearchTargets(baseTarget);
|
||||
if (target != baseTarget && getManager().areElementsEquivalent(element, target)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (element instanceof PsiMethod && target instanceof PsiMethod) {
|
||||
PsiMethod[] superMethods = ((PsiMethod)target).findSuperMethods(false);
|
||||
//noinspection SuspiciousMethodCalls
|
||||
if (Arrays.asList(superMethods).contains(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -597,17 +618,32 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
|
||||
return dot == null ? null : dot.getNode().getElementType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GroovyResolveResult[] multiResolve(boolean incomplete) { //incomplete means we do not take arguments into consideration
|
||||
final ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, incomplete, POLY_RESOLVER);
|
||||
return results.length == 0 ? GroovyResolveResult.EMPTY_ARRAY : (GroovyResolveResult[])results;
|
||||
@Override
|
||||
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
|
||||
return TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, (ref, incomplete) -> {
|
||||
GroovyResolveResult[] regularResults = ref.multiResolve(incomplete, false);
|
||||
if (PsiUtil.isLValueOfOperatorAssignment(this)) {
|
||||
Set<GroovyResolveResult> result = ContainerUtil.newLinkedHashSet();
|
||||
ContainerUtil.addAll(result, ref.multiResolve(incomplete, true));
|
||||
ContainerUtil.addAll(result, regularResults);
|
||||
return result.toArray(GroovyResolveResult.EMPTY_ARRAY);
|
||||
}
|
||||
else {
|
||||
return regularResults;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroovyResolveResult[] multiResolve(boolean incomplete, boolean forceRValue) {
|
||||
return (forceRValue ? myFakeGetterReference : myFakeReference).getValue().multiResolve(incomplete);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public GroovyResolveResult[] getSameNameVariants() {
|
||||
return doPolyResolve(true);
|
||||
return doPolyResolve(true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.lang.psi.impl.statements.expressions
|
||||
|
||||
import com.intellij.psi.PsiPolyVariantReferenceBase
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult
|
||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper
|
||||
|
||||
class GrReferenceExpressionReference(private val ref: GrReferenceExpressionImpl, private val forceRValue: Boolean)
|
||||
: PsiPolyVariantReferenceBase<GrReferenceExpressionImpl>(ref) {
|
||||
|
||||
override fun getVariants(): Array<out Any> = ArrayUtil.EMPTY_OBJECT_ARRAY
|
||||
|
||||
override fun multiResolve(incompleteCode: Boolean): Array<out GroovyResolveResult> {
|
||||
val results = TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode) { ref, incomplete ->
|
||||
ref.ref.doPolyResolve(incompleteCode, forceRValue)
|
||||
}
|
||||
return if (results.isEmpty()) GroovyResolveResult.EMPTY_ARRAY else results
|
||||
}
|
||||
}
|
||||
+13
-5
@@ -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.
|
||||
@@ -159,6 +159,13 @@ public class PsiUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isLValueOfOperatorAssignment(@NotNull GrReferenceExpression element) {
|
||||
PsiElement parent = PsiTreeUtil.skipParentsOfType(element, GrParenthesizedExpression.class);
|
||||
return parent instanceof GrAssignmentExpression
|
||||
&& ((GrAssignmentExpression)parent).getOperationTokenType() != GroovyTokenTypes.mASSIGN
|
||||
&& PsiTreeUtil.isAncestor(((GrAssignmentExpression)parent).getLValue(), element, false);
|
||||
}
|
||||
|
||||
public static boolean isApplicable(@Nullable PsiType[] argumentTypes,
|
||||
PsiMethod method,
|
||||
PsiSubstitutor substitutor,
|
||||
@@ -280,12 +287,13 @@ public class PsiUtil {
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (parent instanceof GrBinaryExpression || parent instanceof GrAssignmentExpression) {
|
||||
GrExpression right = parent instanceof GrBinaryExpression
|
||||
? ((GrBinaryExpression)parent).getRightOperand()
|
||||
: ((GrAssignmentExpression)parent).getRValue();
|
||||
else if (parent instanceof GrBinaryExpression) {
|
||||
GrExpression right = ((GrBinaryExpression)parent).getRightOperand();
|
||||
PsiType type = right != null ? right.getType() : null;
|
||||
return new PsiType[]{notNullizeType(type, nullAsBottom, parent)};
|
||||
} else if (parent instanceof GrAssignmentExpression) {
|
||||
PsiType type = ((GrAssignmentExpression)parent).getType();
|
||||
return new PsiType[]{notNullizeType(type, nullAsBottom, parent)};
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -31,7 +31,7 @@ class GroovyAllVariantsProcessor extends GroovyResolverProcessor {
|
||||
GroovyAllVariantsProcessor(@NotNull GrReferenceExpression ref,
|
||||
@NotNull EnumSet<GroovyResolveKind> kinds,
|
||||
@Nullable GrExpression myUpToArgument) {
|
||||
super(ref, kinds, myUpToArgument);
|
||||
super(ref, kinds, myUpToArgument, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+4
-3
@@ -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.
|
||||
@@ -87,12 +87,13 @@ public abstract class GroovyResolverProcessor implements PsiScopeProcessor, Elem
|
||||
|
||||
GroovyResolverProcessor(@NotNull GrReferenceExpression ref,
|
||||
@NotNull EnumSet<GroovyResolveKind> kinds,
|
||||
@Nullable GrExpression myUpToArgument) {
|
||||
@Nullable GrExpression myUpToArgument,
|
||||
boolean forceRValue) {
|
||||
myRef = ref;
|
||||
myAcceptableKinds = kinds;
|
||||
myName = getReferenceName(ref);
|
||||
|
||||
myIsLValue = PsiUtil.isLValue(myRef);
|
||||
myIsLValue = !forceRValue && PsiUtil.isLValue(myRef);
|
||||
|
||||
myThisType = PsiImplUtil.getQualifierType(ref);
|
||||
myTypeArguments = ref.getTypeArguments();
|
||||
|
||||
+9
-2
@@ -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.
|
||||
@@ -30,6 +30,7 @@ public final class GroovyResolverProcessorBuilder {
|
||||
private boolean myIncomplete = false;
|
||||
private boolean myAllVariants = false;
|
||||
private GrExpression myUpToArgument = null;
|
||||
private boolean myForceRValue = false;
|
||||
|
||||
@NotNull
|
||||
public GroovyResolverProcessor build(GrReferenceExpression ref) {
|
||||
@@ -38,7 +39,7 @@ public final class GroovyResolverProcessorBuilder {
|
||||
return new GroovyAllVariantsProcessor(ref, kinds, myUpToArgument);
|
||||
}
|
||||
else {
|
||||
return new GroovyResolverProcessorImpl(ref, kinds);
|
||||
return new GroovyResolverProcessorImpl(ref, kinds, myForceRValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +65,12 @@ public final class GroovyResolverProcessorBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GroovyResolverProcessorBuilder setForceRValue(boolean forceRValue) {
|
||||
myForceRValue = forceRValue;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static EnumSet<GroovyResolveKind> computeKinds(@NotNull GrReferenceExpression ref) {
|
||||
if (ref.hasAt()) return EnumSet.of(FIELD);
|
||||
|
||||
+3
-3
@@ -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.
|
||||
@@ -38,8 +38,8 @@ class GroovyResolverProcessorImpl extends GroovyResolverProcessor implements GrM
|
||||
|
||||
private final boolean myIsPartOfFqn;
|
||||
|
||||
GroovyResolverProcessorImpl(@NotNull final GrReferenceExpression ref, @NotNull EnumSet<GroovyResolveKind> kinds) {
|
||||
super(ref, kinds, null);
|
||||
GroovyResolverProcessorImpl(@NotNull final GrReferenceExpression ref, @NotNull EnumSet<GroovyResolveKind> kinds, boolean forceRValue) {
|
||||
super(ref, kinds, null, forceRValue);
|
||||
myIsPartOfFqn = ResolveUtil.isPartOfFQN(ref);
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.encapsulateFields.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.plugins.groovy.codeInspection.utils.JavaStylePropertiesUtil
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
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.statements.expressions.*;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||
@@ -151,7 +153,8 @@ public class GroovyEncapsulateFieldHelper extends EncapsulateFieldHelper {
|
||||
PsiClass accessObjectClass = getAccessObject(expr);
|
||||
final PsiResolveHelper helper = JavaPsiFacade.getInstance((expr).getProject()).getResolveHelper();
|
||||
if (helper.isAccessible(fieldDescriptor.getField(), newModifierList, expr, accessObjectClass, null)) {
|
||||
if (expr.resolve() instanceof PsiMethod) {
|
||||
GroovyResolveResult[] results = expr.multiResolve(false);
|
||||
if (ContainerUtil.or(results, it -> it.isValidResult() && it.getElement() instanceof PsiMethod)) {
|
||||
addMemberOperator(expr, field);
|
||||
}
|
||||
return true;
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.lang.resolve
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
|
||||
import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection
|
||||
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression
|
||||
|
||||
class ResolveOperatorAssignmentTest extends GroovyResolveTestCase {
|
||||
|
||||
final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_LATEST
|
||||
|
||||
void 'test resolve both getter & setter'() {
|
||||
fixture.with {
|
||||
configureByText '_.groovy', '''\
|
||||
class A {
|
||||
C plus(B b) {b}
|
||||
}
|
||||
class B {}
|
||||
class C {}
|
||||
class Foo {
|
||||
A getProp() {}
|
||||
Long setProp(C c) {c}
|
||||
}
|
||||
def foo = new Foo()
|
||||
foo.pr<caret>op += new B()
|
||||
'''
|
||||
enableInspections GrUnresolvedAccessInspection, GroovyUnusedDeclarationInspection
|
||||
checkHighlighting()
|
||||
def ref = file.findReferenceAt(editor.caretModel.offset) as GrReferenceExpression
|
||||
def results = ref.multiResolve(false)
|
||||
assert results.size() == 2
|
||||
for (result in results) {
|
||||
assert result.isValidResult()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void 'type reassigned'() {
|
||||
fixture.with {
|
||||
def file = configureByText '_.groovy', '''\
|
||||
class ClassWithPlus {
|
||||
AnotherClass plus(a) {new AnotherClass()}
|
||||
}
|
||||
class AnotherClass {}
|
||||
def c = new ClassWithPlus()
|
||||
c += 1
|
||||
<caret>c
|
||||
'''
|
||||
def expression = file.children.last() as GrReferenceExpression
|
||||
assert expression.type.equalsToText("AnotherClass")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user