From f7e2c127b7ed99dcdfe4eafd0bc0a156067c4c30 Mon Sep 17 00:00:00 2001 From: Zalim Bashorov Date: Wed, 16 Sep 2015 18:45:19 +0300 Subject: [PATCH] Switch to use FakeCallResolver in DelegatedPropertyResolver --- .idea/dictionaries/bashor.xml | 1 + .../kotlin/checkers/CheckerTestUtil.java | 20 ++++++++-- .../resolve/DelegatedPropertyResolver.java | 40 ++++++++++--------- .../types/expressions/FakeCallResolver.kt | 34 +++++++++++----- .../tests/delegatedProperty/missedGetter.kt | 2 +- .../tests/delegatedProperty/missedSetter.kt | 2 +- 6 files changed, 66 insertions(+), 33 deletions(-) diff --git a/.idea/dictionaries/bashor.xml b/.idea/dictionaries/bashor.xml index b149cc91644..f44edba8ebd 100644 --- a/.idea/dictionaries/bashor.xml +++ b/.idea/dictionaries/bashor.xml @@ -3,6 +3,7 @@ ctor lookups + unescape diff --git a/compiler/frontend/src/org/jetbrains/kotlin/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/checkers/CheckerTestUtil.java index 8c463478765..ed34b487053 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/checkers/CheckerTestUtil.java @@ -77,7 +77,8 @@ public class CheckerTestUtil { }; private static final String IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE"; - private static final String DIAGNOSTIC_PARAMETER = "[^\\)\\(;]+"; + private static final String SHOULD_BE_ESCAPED = "\\)\\(;"; + private static final String DIAGNOSTIC_PARAMETER = "(?:(?:\\\\[" + SHOULD_BE_ESCAPED + "])|[^" + SHOULD_BE_ESCAPED + "])+"; private static final String INDIVIDUAL_DIAGNOSTIC = "(\\w+)(\\(" + DIAGNOSTIC_PARAMETER + "(;\\s*" + DIAGNOSTIC_PARAMETER + ")*\\))?"; private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("( parsedParameters = new SmartList(); Matcher parametersMatcher = INDIVIDUAL_PARAMETER_PATTERN.matcher(parameters); while (parametersMatcher.find()) - parsedParameters.add(parametersMatcher.group().trim()); + parsedParameters.add(unescape(parametersMatcher.group().trim())); return new TextDiagnostic(name, parsedParameters); } + private static @NotNull String escape(@NotNull String s) { + return s.replaceAll("([" + SHOULD_BE_ESCAPED + "])", "\\\\$1"); + } + + private static @NotNull String unescape(@NotNull String s) { + return s.replaceAll("\\\\([" + SHOULD_BE_ESCAPED + "])", "$1"); + } + @NotNull public static TextDiagnostic asTextDiagnostic(@NotNull Diagnostic diagnostic) { DiagnosticRenderer renderer = DefaultErrorMessages.getRendererForDiagnostic(diagnostic); @@ -679,7 +688,12 @@ public class CheckerTestUtil { public String asString() { if (parameters == null) return name; - return name + '(' + StringUtil.join(parameters, "; ") + ')'; + return name + '(' + StringUtil.join(parameters, new Function() { + @Override + public String fun(String s) { + return escape(s); + } + }, "; ") + ')'; } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java index efdc4695aed..10679ff5609 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DelegatedPropertyResolver.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve; import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; +import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; @@ -25,13 +26,11 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.rendering.Renderers; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.calls.CallResolver; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem; import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; -import org.jetbrains.kotlin.resolve.calls.util.CallMaker; import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.kotlin.resolve.validation.SymbolUsageValidator; @@ -41,8 +40,10 @@ import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.checker.JetTypeChecker; import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext; import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; +import org.jetbrains.kotlin.types.expressions.FakeCallResolver; import org.jetbrains.kotlin.util.slicedMap.WritableSlice; +import java.util.Collections; import java.util.List; import static org.jetbrains.kotlin.diagnostics.Errors.*; @@ -57,21 +58,23 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.creat public class DelegatedPropertyResolver { public static final Name PROPERTY_DELEGATED_FUNCTION_NAME = Name.identifier("propertyDelegated"); + public static final Name GETTER_NAME = Name.identifier("get"); + public static final Name SETTER_NAME = Name.identifier("set"); @NotNull private final ExpressionTypingServices expressionTypingServices; - @NotNull private final CallResolver callResolver; + @NotNull private final FakeCallResolver fakeCallResolver; @NotNull private final KotlinBuiltIns builtIns; @NotNull private final SymbolUsageValidator symbolUsageValidator; public DelegatedPropertyResolver( @NotNull SymbolUsageValidator symbolUsageValidator, @NotNull KotlinBuiltIns builtIns, - @NotNull CallResolver callResolver, + @NotNull FakeCallResolver fakeCallResolver, @NotNull ExpressionTypingServices expressionTypingServices ) { this.symbolUsageValidator = symbolUsageValidator; this.builtIns = builtIns; - this.callResolver = callResolver; + this.fakeCallResolver = fakeCallResolver; this.expressionTypingServices = expressionTypingServices; } @@ -143,15 +146,15 @@ public class DelegatedPropertyResolver { traceToResolvePDMethod, scope, DataFlowInfo.EMPTY, TypeUtils.NO_EXPECTED_TYPE); - List arguments = Lists.newArrayList(); JetPsiFactory psiFactory = JetPsiFactory(delegateExpression); - arguments.add(createExpressionForPropertyMetadata(psiFactory, propertyDescriptor)); - JetReferenceExpression fakeCalleeExpression = psiFactory.createSimpleName(PROPERTY_DELEGATED_FUNCTION_NAME.asString()); + List arguments = Collections.singletonList(createExpressionForPropertyMetadata(psiFactory, propertyDescriptor)); ExpressionReceiver receiver = new ExpressionReceiver(delegateExpression, delegateType); - Call call = CallMaker.makeCallWithExpressions(fakeCalleeExpression, receiver, null, fakeCalleeExpression, arguments, Call.CallType.DEFAULT); - OverloadResolutionResults functionResults = - callResolver.resolveCallWithGivenName(context, call, fakeCalleeExpression, PROPERTY_DELEGATED_FUNCTION_NAME); + Pair> resolutionResult = + fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, PROPERTY_DELEGATED_FUNCTION_NAME, delegateExpression); + + Call call = resolutionResult.getFirst(); + OverloadResolutionResults functionResults = resolutionResult.getSecond(); if (!functionResults.isSuccess()) { String expectedFunction = renderCall(call, traceToResolvePDMethod.getBindingContext()); @@ -245,7 +248,6 @@ public class DelegatedPropertyResolver { List arguments = Lists.newArrayList(); JetPsiFactory psiFactory = JetPsiFactory(delegateExpression); arguments.add(psiFactory.createExpression(hasThis ? "this" : "null")); - arguments.add(createExpressionForPropertyMetadata(psiFactory, propertyDescriptor)); if (!isGet) { @@ -257,17 +259,17 @@ public class DelegatedPropertyResolver { trace.record(REFERENCE_TARGET, fakeArgument, valueParameters.get(0)); } - Name functionName = Name.identifier(isGet ? "get" : "set"); - JetReferenceExpression fakeCalleeExpression = psiFactory.createSimpleName(functionName.asString()); - + Name functionName = isGet ? GETTER_NAME : SETTER_NAME; ExpressionReceiver receiver = new ExpressionReceiver(delegateExpression, delegateType); - Call call = CallMaker.makeCallWithExpressions(delegateExpression, receiver, null, fakeCalleeExpression, arguments, Call.CallType.DEFAULT); - trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, call); - return callResolver.resolveCallWithGivenName(context, call, fakeCalleeExpression, functionName); + Pair> resolutionResult = + fakeCallResolver.makeAndResolveFakeCallInContext(receiver, context, arguments, functionName, delegateExpression); + + trace.record(BindingContext.DELEGATED_PROPERTY_CALL, accessor, resolutionResult.getFirst()); + return resolutionResult.getSecond(); } - private String renderCall(@NotNull Call call, @NotNull BindingContext context) { + private static String renderCall(@NotNull Call call, @NotNull BindingContext context) { JetExpression calleeExpression = call.getCalleeExpression(); assert calleeExpression != null : "CalleeExpression should exists for fake call of convention method"; StringBuilder builder = new StringBuilder(calleeExpression.getText()); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt index 30093adf7da..65a472a91a9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FakeCallResolver.kt @@ -16,21 +16,20 @@ package org.jetbrains.kotlin.types.expressions -import com.google.common.collect.Lists import com.intellij.openapi.project.Project import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.Call import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.psi.JetPsiFactory +import org.jetbrains.kotlin.psi.JetSimpleNameExpression import org.jetbrains.kotlin.resolve.TemporaryBindingTrace -import org.jetbrains.kotlin.resolve.TraceEntryFilter import org.jetbrains.kotlin.resolve.calls.CallResolver import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults import org.jetbrains.kotlin.resolve.calls.util.CallMaker import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.util.slicedMap.WritableSlice +import org.jetbrains.kotlin.utils.doNothing import java.util.* public class FakeCallResolver( @@ -78,17 +77,34 @@ public class FakeCallResolver( name: Name, callElement: JetExpression? ): Pair> { - val fake = JetPsiFactory(project).createSimpleName("fake") val fakeTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve fake call for", name) - val call = CallMaker.makeCallWithExpressions(callElement ?: fake, receiver, null, fake, valueArguments) - val results = callResolver.resolveCallWithGivenName(context.replaceBindingTrace(fakeTrace), call, fake, name) - if (results.isSuccess()) { + val fakeBindingTrace = context.replaceBindingTrace(fakeTrace) + + return makeAndResolveFakeCallInContext(receiver, fakeBindingTrace, valueArguments, name, callElement) { fake -> fakeTrace.commit({ _, key -> // excluding all entries related to fake expression key != fake }, true) } - return Pair(call, results) } -} \ No newline at end of file + @JvmOverloads + public fun makeAndResolveFakeCallInContext( + receiver: ReceiverValue, + context: ExpressionTypingContext, + valueArguments: List, + name: Name, + callElement: JetExpression?, + onSuccess: (JetSimpleNameExpression) -> Unit = doNothing() + ): Pair> { + val fake = JetPsiFactory(project).createSimpleName(name.asString()) + val call = CallMaker.makeCallWithExpressions(callElement ?: fake, receiver, null, fake, valueArguments) + val results = callResolver.resolveCallWithGivenName(context, call, fake, name) + + if (results.isSuccess) { + onSuccess(fake) + } + + return Pair(call, results) + } +} diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/missedGetter.kt b/compiler/testData/diagnostics/tests/delegatedProperty/missedGetter.kt index 1d318230d19..91cccacc9f6 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/missedGetter.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/missedGetter.kt @@ -1,3 +1,3 @@ -val a: Int by A() +val a: Int by A() class A diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/missedSetter.kt b/compiler/testData/diagnostics/tests/delegatedProperty/missedSetter.kt index 3efd4a7873b..a88d4caddeb 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/missedSetter.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/missedSetter.kt @@ -1,6 +1,6 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER -var a: Int by A() +var a: Int by A() class A { fun get(t: Any?, p: PropertyMetadata): Int {