Add JetInvokeFunctionReference for JetCallExpression
This commit is contained in:
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSuperExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -79,6 +80,10 @@ public class DebugInfoUtil {
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(JetReferenceExpression expression) {
|
||||
if (!BindingContextUtils.isExpressionWithValidReference(expression, bindingContext)){
|
||||
super.visitReferenceExpression(expression);
|
||||
return;
|
||||
}
|
||||
if (expression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) expression;
|
||||
IElementType elementType = expression.getNode().getElementType();
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceService;
|
||||
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -27,11 +30,25 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JetCallExpression extends JetExpressionImpl implements JetCallElement {
|
||||
public class JetCallExpression extends JetReferenceExpression implements JetCallElement {
|
||||
public JetCallExpression(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiReference getReference() {
|
||||
PsiReference[] references = getReferences();
|
||||
if (references.length == 1) return references[0];
|
||||
else return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferences() {
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull JetVisitorVoid visitor) {
|
||||
visitor.visitCallExpression(this);
|
||||
|
||||
@@ -229,7 +229,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
|
||||
}
|
||||
|
||||
public void visitCallExpression(JetCallExpression expression) {
|
||||
visitExpression(expression);
|
||||
visitReferenceExpression(expression);
|
||||
}
|
||||
|
||||
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInfo;
|
||||
@@ -297,7 +299,7 @@ public class BindingContextUtils {
|
||||
if (result.getDataFlowInfo() != DataFlowInfo.EMPTY) {
|
||||
trace.record(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression, result.getDataFlowInfo());
|
||||
}
|
||||
if (!(expression instanceof JetReferenceExpression)) {
|
||||
if (!isExpressionWithValidReference(expression, trace.getBindingContext())) {
|
||||
trace.record(BindingContext.RESOLUTION_SCOPE, expression, resolutionScope);
|
||||
}
|
||||
}
|
||||
@@ -312,4 +314,33 @@ public class BindingContextUtils {
|
||||
JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||
return JetTypeInfo.create(type, dataFlowInfo);
|
||||
}
|
||||
|
||||
public static boolean isExpressionWithValidReference(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull BindingContext context
|
||||
) {
|
||||
if (!(expression instanceof JetReferenceExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(expression instanceof JetCallExpression)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isCallExpressionWithValidReference(expression, context);
|
||||
}
|
||||
|
||||
public static boolean isCallExpressionWithValidReference(
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull BindingContext context
|
||||
) {
|
||||
if (expression instanceof JetCallExpression) {
|
||||
JetExpression calleeExpression = ((JetCallExpression) expression).getCalleeExpression();
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = context.get(BindingContext.RESOLVED_CALL, calleeExpression);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +304,23 @@ public class CandidateResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
recordReferenceForInvokeFunction(context);
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> void recordReferenceForInvokeFunction(CallCandidateResolutionContext<D> context) {
|
||||
// TODO Replace using CallForImplicitInvoke
|
||||
JetExpression calleeExpression = context.call.getCalleeExpression();
|
||||
if (calleeExpression != null) {
|
||||
PsiElement parent = calleeExpression.getParent();
|
||||
if (parent instanceof JetCallExpression) {
|
||||
JetCallExpression callExpression = (JetCallExpression) parent;
|
||||
if (BindingContextUtils.isCallExpressionWithValidReference(callExpression, context.trace.getBindingContext())) {
|
||||
CallableDescriptor resultingDescriptor = context.candidateCall.getResultingDescriptor();
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, callExpression, resultingDescriptor.getReturnType());
|
||||
context.trace.record(BindingContext.REFERENCE_TARGET, callExpression, resultingDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <D extends CallableDescriptor> void addConstraintForFunctionLiteral(
|
||||
@@ -372,7 +389,7 @@ public class CandidateResolver {
|
||||
}
|
||||
|
||||
TypeSubstitutor substituteDontCare = ConstraintSystemWithPriorities
|
||||
.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
|
||||
.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
|
||||
|
||||
// Value parameters
|
||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
|
||||
@@ -446,7 +463,7 @@ public class CandidateResolver {
|
||||
JetType expectedType = substitutor.substitute(effectiveExpectedType, Variance.INVARIANT);
|
||||
CallResolutionContext newContext = context.replaceBindingTrace(traceToResolveArgument).replaceExpectedType(expectedType);
|
||||
JetTypeInfo typeInfoForCall = argumentTypeResolver.getArgumentTypeInfo(argumentExpression, newContext,
|
||||
resolveFunctionArgumentBodies, traceToResolveArgument);
|
||||
resolveFunctionArgumentBodies, traceToResolveArgument);
|
||||
JetType type = typeInfoForCall.getType();
|
||||
constraintSystem.addSubtypeConstraint(type, effectiveExpectedType, ConstraintPosition.getValueParameterPosition(
|
||||
valueParameterDescriptor.getIndex()));
|
||||
|
||||
@@ -254,7 +254,7 @@ public class ResolveSessionUtils {
|
||||
DelegatingBindingTrace trace = new DelegatingBindingTrace(
|
||||
resolveSession.getBindingContext(), "trace to resolve a member scope of expression", expression);
|
||||
|
||||
if (expression instanceof JetReferenceExpression) {
|
||||
if (BindingContextUtils.isExpressionWithValidReference(expression, resolveSession.getBindingContext())) {
|
||||
QualifiedExpressionResolver qualifiedExpressionResolver = resolveSession.getInjector().getQualifiedExpressionResolver();
|
||||
|
||||
// In some type declaration
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
|
||||
result = JetTypeInfo.create(null, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
if (!context.trace.get(BindingContext.PROCESSED, expression) && !(expression instanceof JetReferenceExpression)) {
|
||||
if (!context.trace.get(BindingContext.PROCESSED, expression) && !BindingContextUtils.isExpressionWithValidReference(expression, context.trace.getBindingContext())) {
|
||||
context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
|
||||
}
|
||||
context.trace.record(BindingContext.PROCESSED, expression);
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.references;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetValueArgumentList;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
|
||||
|
||||
class JetInvokeFunctionReference extends JetPsiReference implements MultiRangeReference {
|
||||
|
||||
public static PsiReference[] create(@NotNull JetCallExpression expression) {
|
||||
return new PsiReference[] { new JetInvokeFunctionReference(expression) };
|
||||
}
|
||||
|
||||
public JetInvokeFunctionReference(@NotNull JetCallExpression expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange getRangeInElement() {
|
||||
return getElement().getTextRange().shiftRight(-getElement().getTextOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiElement doResolve() {
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
|
||||
(JetFile) getElement().getContainingFile()).getBindingContext();
|
||||
ResolvedCall<? extends CallableDescriptor> invokeFunction =
|
||||
bindingContext.get(RESOLVED_CALL, ((JetCallExpression) myExpression).getCalleeExpression());
|
||||
if (invokeFunction != null && invokeFunction instanceof VariableAsFunctionResolvedCall) {
|
||||
FunctionDescriptor resultingDescriptor = ((VariableAsFunctionResolvedCall) invokeFunction).getResultingDescriptor();
|
||||
PsiElement invokeFunctionElement = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, resultingDescriptor);
|
||||
return invokeFunctionElement;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
// TODO If there are more than one invoke(), add all function ("ambiguity"). See JetPsiReference
|
||||
PsiElement element = doResolve();
|
||||
if (element == null) {
|
||||
return ResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
return new ResolveResult[] {new PsiElementResolveResult(element, true)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TextRange> getRanges() {
|
||||
List<TextRange> list = new ArrayList<TextRange>();
|
||||
JetValueArgumentList valueArgumentList = ((JetCallExpression) myExpression).getValueArgumentList();
|
||||
if (valueArgumentList == null) {
|
||||
return list;
|
||||
}
|
||||
if (valueArgumentList.getArguments().size() > 0) {
|
||||
ASTNode valueArgumentListNode = valueArgumentList.getNode();
|
||||
ASTNode lPar = valueArgumentListNode.findChildByType(JetTokens.LPAR);
|
||||
if (lPar != null) {
|
||||
list.add(getRange(lPar));
|
||||
}
|
||||
|
||||
ASTNode rPar = valueArgumentListNode.findChildByType(JetTokens.RPAR);
|
||||
if (rPar != null) {
|
||||
list.add(getRange(rPar));
|
||||
}
|
||||
}
|
||||
else {
|
||||
list.add(getRange(valueArgumentList.getNode()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private TextRange getRange(ASTNode node) {
|
||||
TextRange textRange = node.getTextRange();
|
||||
return textRange.shiftRight(-myExpression.getTextOffset());
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetThisReferenceExpression;
|
||||
|
||||
@@ -54,5 +55,14 @@ public class JetReferenceContributor extends PsiReferenceContributor {
|
||||
return JetArrayAccessReference.create((JetArrayAccessExpression) element);
|
||||
}
|
||||
});
|
||||
|
||||
registrar.registerReferenceProvider(psiElement(JetCallExpression.class),
|
||||
new PsiReferenceProvider() {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext processingContext) {
|
||||
return JetInvokeFunctionReference.create((JetCallExpression) element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
fun main(args: Array<String>) {
|
||||
throw IllegalAccessExceptio<caret>() //Press Ctrl+Space and select it
|
||||
throw IllegalAccessExceptio<caret> //Press Ctrl+Space and select it
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
fun main(args: Array<String>) {
|
||||
throw IllegalAccessException<caret>() //Press Ctrl+Space and select it
|
||||
throw IllegalAccessException<caret> //Press Ctrl+Space and select it
|
||||
}
|
||||
@@ -9,5 +9,5 @@ class A {
|
||||
}
|
||||
|
||||
fun testMy() {
|
||||
A.testOthe<caret>()
|
||||
A.testOthe<caret>
|
||||
}
|
||||
@@ -326,7 +326,10 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@NotNull
|
||||
public JsNode visitThisExpression(@NotNull JetThisExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
return context.getThisObject(getDescriptorForReferenceExpression(context.bindingContext(), expression.getInstanceReference()));
|
||||
DeclarationDescriptor thisExpression =
|
||||
getDescriptorForReferenceExpression(context.bindingContext(), expression.getInstanceReference());
|
||||
assert thisExpression != null : "This expression must reference a descriptor: " + expression.getText();
|
||||
return context.getThisObject(thisExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ public final class ReferenceAccessTranslator extends AbstractTranslator implemen
|
||||
/*package*/ static ReferenceAccessTranslator newInstance(@NotNull JetSimpleNameExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
DeclarationDescriptor referenceDescriptor = getDescriptorForReferenceExpression(context.bindingContext(), expression);
|
||||
assert referenceDescriptor != null : "JetSimpleName expression must reference a descriptor " + expression.getText();
|
||||
return new ReferenceAccessTranslator(referenceDescriptor, context);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,13 +123,16 @@ public final class BindingUtils {
|
||||
return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context,
|
||||
@NotNull JetReferenceExpression reference) {
|
||||
DeclarationDescriptor referencedDescriptor = getNullableDescriptorForReferenceExpression(context, reference);
|
||||
assert referencedDescriptor != null
|
||||
: message(reference, "Reference expression must reference a descriptor for reference " + reference.getText());
|
||||
return referencedDescriptor;
|
||||
if (BindingContextUtils.isExpressionWithValidReference(reference, context)) {
|
||||
assert referencedDescriptor != null
|
||||
: message(reference, "Reference expression must reference a descriptor for reference " + reference.getText());
|
||||
return referencedDescriptor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user