diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/DebugInfoUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/DebugInfoUtil.java index 5cdf0554c47..a7dd3482ab6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/DebugInfoUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/DebugInfoUtil.java @@ -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(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java index a00f9f92ae2..80e8548375a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVisitorVoid.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVisitorVoid.java index 6d72dee68d5..6ed38047045 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVisitorVoid.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetVisitorVoid.java @@ -229,7 +229,7 @@ public class JetVisitorVoid extends PsiElementVisitor { } public void visitCallExpression(JetCallExpression expression) { - visitExpression(expression); + visitReferenceExpression(expression); } public void visitArrayAccessExpression(JetArrayAccessExpression expression) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index 850dbeb03ce..ed425e0f8b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -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 resolvedCall = context.get(BindingContext.RESOLVED_CALL, calleeExpression); + if (resolvedCall instanceof VariableAsFunctionResolvedCall) { + return true; + } + } + return false; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 0a38520bfba..028a0364781 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -304,6 +304,23 @@ public class CandidateResolver { } } } + recordReferenceForInvokeFunction(context); + } + + private void recordReferenceForInvokeFunction(CallCandidateResolutionContext 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 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 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())); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java index 115ecfd8f6d..936d9c2b1fd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSessionUtils.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index e4ba036ea08..a1ac70bc264 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -131,7 +131,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor 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 getRanges() { + List list = new ArrayList(); + 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()); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetReferenceContributor.java b/idea/src/org/jetbrains/jet/plugin/references/JetReferenceContributor.java index 49cfbf19ba5..405440eb192 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetReferenceContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetReferenceContributor.java @@ -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); + } + }); } } diff --git a/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt b/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt index a2ec4592038..5a427810b80 100644 --- a/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt +++ b/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt @@ -1,3 +1,3 @@ fun main(args: Array) { - throw IllegalAccessExceptio() //Press Ctrl+Space and select it + throw IllegalAccessExceptio //Press Ctrl+Space and select it } \ No newline at end of file diff --git a/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt.after b/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt.after index 13d0a0cebad..9ad8ebc6547 100644 --- a/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt.after +++ b/idea/testData/completion/handlers/DoNotInsertImportIfResolvedIntoJavaConstructor.kt.after @@ -1,3 +1,3 @@ fun main(args: Array) { - throw IllegalAccessException() //Press Ctrl+Space and select it + throw IllegalAccessException //Press Ctrl+Space and select it } \ No newline at end of file diff --git a/idea/testData/completion/handlers/ExistingSingleBrackets.kt b/idea/testData/completion/handlers/ExistingSingleBrackets.kt index 36a6633ffa9..141815f2397 100644 --- a/idea/testData/completion/handlers/ExistingSingleBrackets.kt +++ b/idea/testData/completion/handlers/ExistingSingleBrackets.kt @@ -9,5 +9,5 @@ class A { } fun testMy() { - A.testOthe() + A.testOthe } \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 9cc0945c998..bc190e3f32d 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -326,7 +326,10 @@ public final class ExpressionVisitor extends TranslatorVisitor { @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 diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceAccessTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceAccessTranslator.java index 198ea99d249..9dc395ca5b1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceAccessTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceAccessTranslator.java @@ -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); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 6aa825aa907..d54bb560144 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -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