Synthetic accessors for class object private members

#KT-3338 Fixed
This commit is contained in:
Mikhael Bogdanov
2013-06-10 18:14:05 +04:00
parent 4ef2f997ed
commit 47fe81471a
32 changed files with 542 additions and 146 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.jet.di;
import org.jetbrains.jet.lang.resolve.BodyResolver;
import org.jetbrains.jet.lang.resolve.calls.NeedSyntheticCallResolverExtension;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -42,6 +43,7 @@ import javax.annotation.PreDestroy;
public class InjectorForBodyResolve {
private BodyResolver bodyResolver;
private NeedSyntheticCallResolverExtension needSyntheticCallResolverExtension;
private final Project project;
private final TopDownAnalysisParameters topDownAnalysisParameters;
private final BindingTrace bindingTrace;
@@ -69,6 +71,7 @@ public class InjectorForBodyResolve {
@NotNull ModuleDescriptor moduleDescriptor
) {
this.bodyResolver = new BodyResolver();
this.needSyntheticCallResolverExtension = new NeedSyntheticCallResolverExtension();
this.project = project;
this.topDownAnalysisParameters = topDownAnalysisParameters;
this.bindingTrace = bindingTrace;
@@ -101,6 +104,7 @@ public class InjectorForBodyResolve {
callResolver.setArgumentTypeResolver(argumentTypeResolver);
callResolver.setCandidateResolver(candidateResolver);
callResolver.setExpressionTypingServices(expressionTypingServices);
callResolver.setExtension(needSyntheticCallResolverExtension);
callResolver.setTypeResolver(typeResolver);
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.psi.JetImportsFactory;
import org.jetbrains.jet.lang.resolve.calls.NeedSyntheticCallResolverExtension;
import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.ArgumentTypeResolver;
@@ -46,6 +47,7 @@ public class InjectorForLazyResolve {
private AnnotationResolver annotationResolver;
private QualifiedExpressionResolver qualifiedExpressionResolver;
private JetImportsFactory jetImportsFactory;
private NeedSyntheticCallResolverExtension needSyntheticCallResolverExtension;
private CallExpressionResolver callExpressionResolver;
private CallResolver callResolver;
private ArgumentTypeResolver argumentTypeResolver;
@@ -66,6 +68,7 @@ public class InjectorForLazyResolve {
this.annotationResolver = new AnnotationResolver();
this.qualifiedExpressionResolver = new QualifiedExpressionResolver();
this.jetImportsFactory = new JetImportsFactory();
this.needSyntheticCallResolverExtension = new NeedSyntheticCallResolverExtension();
this.callExpressionResolver = new CallExpressionResolver();
this.callResolver = new CallResolver();
this.argumentTypeResolver = new ArgumentTypeResolver();
@@ -96,6 +99,7 @@ public class InjectorForLazyResolve {
callResolver.setArgumentTypeResolver(argumentTypeResolver);
callResolver.setCandidateResolver(candidateResolver);
callResolver.setExpressionTypingServices(expressionTypingServices);
callResolver.setExtension(needSyntheticCallResolverExtension);
callResolver.setTypeResolver(typeResolver);
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
@@ -17,6 +17,7 @@
package org.jetbrains.jet.di;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.resolve.calls.NeedSyntheticCallResolverExtension;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.resolve.calls.CallExpressionResolver;
@@ -34,6 +35,7 @@ import javax.annotation.PreDestroy;
public class InjectorForMacros {
private ExpressionTypingServices expressionTypingServices;
private NeedSyntheticCallResolverExtension needSyntheticCallResolverExtension;
private final Project project;
private final ModuleDescriptor moduleDescriptor;
private CallExpressionResolver callExpressionResolver;
@@ -50,6 +52,7 @@ public class InjectorForMacros {
@NotNull ModuleDescriptor moduleDescriptor
) {
this.expressionTypingServices = new ExpressionTypingServices();
this.needSyntheticCallResolverExtension = new NeedSyntheticCallResolverExtension();
this.project = project;
this.moduleDescriptor = moduleDescriptor;
this.callExpressionResolver = new CallExpressionResolver();
@@ -72,6 +75,7 @@ public class InjectorForMacros {
callResolver.setArgumentTypeResolver(argumentTypeResolver);
callResolver.setCandidateResolver(candidateResolver);
callResolver.setExpressionTypingServices(expressionTypingServices);
callResolver.setExtension(needSyntheticCallResolverExtension);
callResolver.setTypeResolver(typeResolver);
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
@@ -22,6 +22,7 @@ import org.jetbrains.jet.lang.resolve.BodyResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.calls.NeedSyntheticCallResolverExtension;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -56,6 +57,7 @@ public class InjectorForTopDownAnalyzerBasic {
private ControlFlowAnalyzer controlFlowAnalyzer;
private DeclarationsChecker declarationsChecker;
private DescriptorResolver descriptorResolver;
private NeedSyntheticCallResolverExtension needSyntheticCallResolverExtension;
private final Project project;
private final TopDownAnalysisParameters topDownAnalysisParameters;
private final BindingTrace bindingTrace;
@@ -91,6 +93,7 @@ public class InjectorForTopDownAnalyzerBasic {
this.controlFlowAnalyzer = new ControlFlowAnalyzer();
this.declarationsChecker = new DeclarationsChecker();
this.descriptorResolver = new DescriptorResolver();
this.needSyntheticCallResolverExtension = new NeedSyntheticCallResolverExtension();
this.project = project;
this.topDownAnalysisParameters = topDownAnalysisParameters;
this.bindingTrace = bindingTrace;
@@ -162,6 +165,7 @@ public class InjectorForTopDownAnalyzerBasic {
callResolver.setArgumentTypeResolver(argumentTypeResolver);
callResolver.setCandidateResolver(candidateResolver);
callResolver.setExpressionTypingServices(expressionTypingServices);
callResolver.setExtension(needSyntheticCallResolverExtension);
callResolver.setTypeResolver(typeResolver);
argumentTypeResolver.setExpressionTypingServices(expressionTypingServices);
@@ -133,6 +133,8 @@ public interface BindingContext {
WritableSlice<VariableDescriptor, CaptureKind> CAPTURED_IN_CLOSURE = new BasicWritableSlice<VariableDescriptor, CaptureKind>(DO_NOTHING);
WritableSlice<CallableMemberDescriptor, Boolean> NEED_SYNTHETIC_ACCESSOR = new BasicWritableSlice<CallableMemberDescriptor, Boolean>(DO_NOTHING);
// enum DeferredTypeKey {DEFERRED_TYPE_KEY}
// WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice();
@@ -420,10 +420,24 @@ public class DescriptorUtils {
return (ClassDescriptor) classifier;
}
@NotNull
public static ConstructorDescriptor getConstructorOfDataClass(ClassDescriptor classDescriptor) {
ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
assert descriptor != null : "Data class must have only one constructor: " + classDescriptor.getConstructors();
return descriptor;
}
@NotNull
public static ConstructorDescriptor getConstructorOfSingletonObject(ClassDescriptor classDescriptor) {
ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
assert descriptor != null : "Class of singleton object must have only one constructor: " + classDescriptor.getConstructors();
return descriptor;
}
@Nullable
private static ConstructorDescriptor getConstructorDescriptorIfOnlyOne(ClassDescriptor classDescriptor) {
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
assert constructors.size() == 1 : "Data class must have only one constructor: " + constructors;
return constructors.iterator().next();
return constructors.size() != 1 ? null : constructors.iterator().next();
}
@Nullable
@@ -21,6 +21,7 @@ import com.google.common.collect.Lists;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
@@ -70,6 +71,8 @@ public class CallResolver {
private CandidateResolver candidateResolver;
@NotNull
private ArgumentTypeResolver argumentTypeResolver;
@Nullable
private CallResolverExtension extension;
@Inject
public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
@@ -91,6 +94,11 @@ public class CallResolver {
this.argumentTypeResolver = argumentTypeResolver;
}
@Inject
public void setExtension(@NotNull CallResolverExtension extension) {
this.extension = extension;
}
@NotNull
public OverloadResolutionResults<VariableDescriptor> resolveSimpleProperty(@NotNull BasicCallResolutionContext context) {
JetExpression calleeExpression = context.call.getCalleeExpression();
@@ -142,7 +150,7 @@ public class CallResolver {
ProgressIndicatorProvider.checkCanceled();
List<ResolutionTask<CallableDescriptor, FunctionDescriptor>> prioritizedTasks;
JetExpression calleeExpression = context.call.getCalleeExpression();
JetReferenceExpression functionReference;
if (calleeExpression instanceof JetSimpleNameExpression) {
@@ -239,7 +247,7 @@ public class CallResolver {
}
return checkArgumentTypesAndFail(context);
}
FunctionDescriptorImpl functionDescriptor = new ExpressionAsFunctionDescriptor(context.scope.getContainingDeclaration(), Name.special("<for expression " + calleeExpression.getText() + ">"));
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType, NO_RECEIVER_PARAMETER, Modality.FINAL,
Visibilities.LOCAL);
@@ -296,12 +304,17 @@ public class CallResolver {
}
traceToResolveCall.commit();
if (prioritizedTasks.isEmpty()) {
return results;
if (prioritizedTasks.isEmpty() || context.resolveMode == ResolveMode.NESTED_CALL) {
//do nothing
} else {
results = completeTypeInferenceDependentOnExpectedType(context, results, tracing);
}
if (context.resolveMode == ResolveMode.NESTED_CALL) return results;
return completeTypeInferenceDependentOnExpectedType(context, results, tracing);
if (extension != null) {
extension.run(results, context);
}
return results;
}
private <D extends CallableDescriptor> void completeTypeInferenceDependentOnFunctionLiterals(
@@ -0,0 +1,26 @@
/*
* 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.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
public interface CallResolverExtension {
<F extends CallableDescriptor> void run(@NotNull OverloadResolutionResultsImpl<F> results, @NotNull BasicCallResolutionContext context);
}
@@ -0,0 +1,54 @@
/*
* 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.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.Visibilities;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCallWithTrace;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import static org.jetbrains.jet.lang.resolve.BindingContext.NEED_SYNTHETIC_ACCESSOR;
public class NeedSyntheticCallResolverExtension implements CallResolverExtension {
@Override
public <F extends CallableDescriptor> void run(
@NotNull OverloadResolutionResultsImpl<F> results,
@NotNull BasicCallResolutionContext context
) {
if (results.isSingleResult()) {
ResolvedCallWithTrace<F> resolvedCall = results.getResultingCall();
CallableDescriptor targetDescriptor = resolvedCall.getResultingDescriptor();
if (needSyntheticAccessor(context.scope, targetDescriptor)) {
context.trace.record(NEED_SYNTHETIC_ACCESSOR, (CallableMemberDescriptor) targetDescriptor, Boolean.TRUE);
}
}
}
//Necessary synthetic accessors in outer classes generated via old logic: CodegenContext.getAccessor
//Generation of accessors in nested classes (to invoke from outer,
// e.g.: from class to classobject) controlled via NEED_SYNTHETIC_ACCESSOR slice
private boolean needSyntheticAccessor(JetScope invokationScope, CallableDescriptor targetDescriptor) {
return targetDescriptor instanceof CallableMemberDescriptor &&
targetDescriptor.getVisibility() == Visibilities.PRIVATE &&
targetDescriptor.getContainingDeclaration() != invokationScope.getContainingDeclaration().getContainingDeclaration();
}
}