Resolve "componentN" functions for data classes

Reuse existing (but not used) VALUE_PARAMETER_AS_PROPERTY in
BindingContext to store mapping from constructor's value parameters to
property descriptors.

Create a new slice DATA_CLASS_COMPONENT_FUNCTION to store mapping from
constructor's value parameters to generated componentN functions.
This commit is contained in:
Alexander Udalov
2012-08-28 20:05:32 +04:00
parent 410922c58d
commit b93db69a24
21 changed files with 285 additions and 4 deletions
@@ -220,8 +220,11 @@ public interface BindingContext {
.setFurtherLookupSlices(DECLARATIONS_TO_DESCRIPTORS).build();
WritableSlice<JetReferenceExpression, PsiElement> LABEL_TARGET = Slices.<JetReferenceExpression, PsiElement>sliceBuilder().build();
WritableSlice<JetParameter, PropertyDescriptor> VALUE_PARAMETER_AS_PROPERTY =
Slices.<JetParameter, PropertyDescriptor>sliceBuilder().build();
WritableSlice<ValueParameterDescriptor, PropertyDescriptor> VALUE_PARAMETER_AS_PROPERTY =
Slices.<ValueParameterDescriptor, PropertyDescriptor>sliceBuilder().build();
WritableSlice<ValueParameterDescriptor, FunctionDescriptor> DATA_CLASS_COMPONENT_FUNCTION =
Slices.<ValueParameterDescriptor, FunctionDescriptor>sliceBuilder().build();
WritableSlice<FqName, ClassDescriptor> FQNAME_TO_CLASS_DESCRIPTOR = new BasicWritableSlice<FqName, ClassDescriptor>(DO_NOTHING, true);
WritableSlice<FqName, NamespaceDescriptor> FQNAME_TO_NAMESPACE_DESCRIPTOR =
@@ -28,6 +28,8 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import javax.inject.Inject;
import java.util.*;
@@ -88,6 +90,7 @@ public class DeclarationResolver {
resolveConstructorHeaders();
resolveAnnotationStubsOnClassesAndConstructors();
resolveFunctionAndPropertyHeaders();
createComponentFunctionsForDataClasses();
importsResolver.processMembersImports(rootScope);
checkRedeclarationsInNamespaces();
checkRedeclarationsInInnerClassNames();
@@ -210,6 +213,38 @@ public class DeclarationResolver {
}
}
private void createComponentFunctionsForDataClasses() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
JetClass jetClass = entry.getKey();
MutableClassDescriptor classDescriptor = entry.getValue();
if (jetClass.hasPrimaryConstructor() && JetStandardLibrary.isData(classDescriptor)) {
createComponentFunctions(classDescriptor);
}
}
}
private void createComponentFunctions(MutableClassDescriptor classDescriptor) {
Set<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
assert constructors.size() == 1 : "Data class hasn't a single constructor: " + constructors.size();
ConstructorDescriptor constructor = constructors.iterator().next();
int parameterIndex = 0;
for (ValueParameterDescriptor parameter : constructor.getValueParameters()) {
if (!ErrorUtils.isErrorType(parameter.getType())) {
PropertyDescriptor property = trace.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter);
if (property != null) {
++parameterIndex;
SimpleFunctionDescriptor functionDescriptor =
DescriptorResolver.createComponentFunctionDescriptor(parameterIndex, property, parameter, classDescriptor, trace);
classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor);
}
}
}
}
private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) {
if (classDescriptor.getKind() == ClassKind.TRAIT) {
JetParameterList primaryConstructorParameterList = klass.getPrimaryConstructorParameterList();
@@ -58,6 +58,7 @@ import static org.jetbrains.jet.lexer.JetTokens.OVERRIDE_KEYWORD;
public class DescriptorResolver {
public static final Name VALUE_OF_METHOD_NAME = Name.identifier("valueOf");
public static final Name VALUES_METHOD_NAME = Name.identifier("values");
public static final String COMPONENT_FUNCTION_NAME_PREFIX = "component";
@NotNull
private TypeResolver typeResolver;
@@ -295,6 +296,40 @@ public class DescriptorResolver {
return functionDescriptor;
}
@NotNull
public static SimpleFunctionDescriptor createComponentFunctionDescriptor(
int parameterIndex,
@NotNull PropertyDescriptor property,
@NotNull ValueParameterDescriptor parameter,
@NotNull ClassDescriptor classDescriptor,
@NotNull BindingTrace trace
) {
String functionName = COMPONENT_FUNCTION_NAME_PREFIX + parameterIndex;
JetType returnType = property.getType();
SimpleFunctionDescriptorImpl functionDescriptor = new SimpleFunctionDescriptorImpl(
classDescriptor,
Collections.<AnnotationDescriptor>emptyList(),
Name.identifier(functionName),
CallableMemberDescriptor.Kind.SYNTHESIZED
);
functionDescriptor.initialize(
null,
classDescriptor.getImplicitReceiver(),
Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(),
returnType,
Modality.FINAL,
property.getVisibility(),
true
);
trace.record(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter, functionDescriptor);
return functionDescriptor;
}
public static Visibility getDefaultVisibility(JetModifierListOwner modifierListOwner, DeclarationDescriptor containingDescriptor) {
Visibility defaultVisibility;
if (containingDescriptor instanceof ClassDescriptor) {
@@ -1076,6 +1111,7 @@ public class DescriptorResolver {
getter.initialize(propertyDescriptor.getType());
trace.record(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter, propertyDescriptor);
trace.record(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter, propertyDescriptor);
return propertyDescriptor;
}
@@ -277,7 +277,7 @@ public class ExpressionTypingUtils {
) {
int componentIndex = 1;
for (JetMultiDeclarationEntry entry : multiDeclaration.getEntries()) {
final Name componentName = Name.identifier("component" + componentIndex);
final Name componentName = Name.identifier(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX + componentIndex);
componentIndex++;
JetType expectedType = getExpectedTypeForComponent(context, entry);