JET-18 Resolve references to value parameters of the primary constructor to parameter or property descriptors according to the semantics

This commit is contained in:
Andrey Breslav
2011-05-03 23:21:56 +04:00
parent fe36a55a94
commit dae06f0b67
13 changed files with 99 additions and 27 deletions
@@ -307,9 +307,8 @@ public class ClassCodegen {
for (JetParameter p : aClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p);
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
@@ -341,9 +340,8 @@ public class ClassCodegen {
for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
VariableDescriptor descriptor = bindingContext.getParameterDescriptor(p);
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, kind);
@@ -222,7 +222,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateForInArray(JetForExpression expression, Type loopRangeType) {
final JetParameter loopParameter = expression.getLoopParameter();
final VariableDescriptor parameterDescriptor = bindingContext.getParameterDescriptor(loopParameter);
final VariableDescriptor parameterDescriptor = bindingContext.getVariableDescriptor(loopParameter);
JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType);
@@ -269,7 +269,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateForInIterable(JetForExpression expression, Type loopRangeType) {
final JetParameter loopParameter = expression.getLoopParameter();
final VariableDescriptor parameterDescriptor = bindingContext.getParameterDescriptor(loopParameter);
final VariableDescriptor parameterDescriptor = bindingContext.getVariableDescriptor(loopParameter);
JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType);
@@ -99,18 +99,18 @@ public class JetPsiChecker implements Annotator {
VariableDescriptor propertyDescriptor = bindingContext.getVariableDescriptor(property);
if (propertyDescriptor instanceof PropertyDescriptor) {
if (bindingContext.hasBackingField((PropertyDescriptor) propertyDescriptor)) {
holder.createInfoAnnotation(
property.getNameIdentifier(),
"This property has a backing field")
.setTextAttributes(JetHighlighter.JET_PROPERTY_WITH_BACKING_FIELD_IDENTIFIER);
putBackingfieldAnnotation(holder, property);
}
}
}
// @Override
// public void visitParameter(JetParameter parameter) {
// bindingContext.get
// }
@Override
public void visitParameter(JetParameter parameter) {
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(parameter);
if (propertyDescriptor != null && bindingContext.hasBackingField(propertyDescriptor)) {
putBackingfieldAnnotation(holder, parameter);
}
}
@Override
public void visitJetElement(JetElement elem) {
@@ -118,4 +118,11 @@ public class JetPsiChecker implements Annotator {
}
});
}
private void putBackingfieldAnnotation(AnnotationHolder holder, JetNamedDeclaration element) {
holder.createInfoAnnotation(
element.getNameIdentifier(),
"This property has a backing field")
.setTextAttributes(JetHighlighter.JET_PROPERTY_WITH_BACKING_FIELD_IDENTIFIER);
}
}
@@ -14,8 +14,11 @@ public interface BindingContext {
TypeParameterDescriptor getTypeParameterDescriptor(JetTypeParameter declaration);
FunctionDescriptor getFunctionDescriptor(JetFunction declaration);
ConstructorDescriptor getConstructorDescriptor(JetElement declaration);
VariableDescriptor getVariableDescriptor(JetProperty declaration);
VariableDescriptor getParameterDescriptor(JetParameter declaration);
VariableDescriptor getVariableDescriptor(JetParameter declaration);
PropertyDescriptor getPropertyDescriptor(JetParameter primaryConstructorParameter);
JetType getExpressionType(JetExpression expression);
@@ -24,7 +24,8 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
private final Map<DeclarationDescriptor, PsiElement> descriptorToDeclarations = new HashMap<DeclarationDescriptor, PsiElement>();
private final Map<PsiElement, DeclarationDescriptor> declarationsToDescriptors = new HashMap<PsiElement, DeclarationDescriptor>();
private final Map<PsiElement, ConstructorDescriptor> constructorDeclarationsToDescriptors = new HashMap<PsiElement, ConstructorDescriptor>();
private final Map<PsiElement, PropertyDescriptor> propertyDeclarationsToDescriptors = Maps.newHashMap();
private final Map<PsiElement, NamespaceDescriptor> namespaceDeclarationsToDescriptors = Maps.newHashMap();
private final Map<PsiElement, PropertyDescriptor> primaryConstructorParameterDeclarationsToPropertyDescriptors = Maps.newHashMap();
private final Set<JetFunctionLiteralExpression> blocks = new HashSet<JetFunctionLiteralExpression>();
private final Set<JetElement> statements = new HashSet<JetElement>();
private final Set<PropertyDescriptor> backingFieldRequired = new HashSet<PropertyDescriptor>();
@@ -68,9 +69,12 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
return null;
}
@Override
public Void visitNamespaceDescriptor(NamespaceDescriptor descriptor, PsiElement declaration) {
namespaceDeclarationsToDescriptors.put(declaration, descriptor);
return null;
}
public Void visitDeclarationDescriptor(DeclarationDescriptor descriptor, PsiElement declaration) {
safePut(declarationsToDescriptors, declaration, descriptor.getOriginal());
return null;
@@ -78,10 +82,16 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
}, declaration);
}
@Override
public void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor) {
safePut(primaryConstructorParameterDeclarationsToPropertyDescriptors, declaration, descriptor);
safePut(descriptorToDeclarations, descriptor.getOriginal(), declaration);
}
private <K, V> void safePut(Map<K, V> map, K key, V value) {
V oldValue = map.put(key, value);
// TODO:
// assert oldValue == null || oldValue == value : key + ": " + oldValue + " and " + value;
assert oldValue == null || oldValue == value : key + ": " + oldValue + " and " + value;
}
@Override
@@ -112,7 +122,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
public NamespaceDescriptor getNamespaceDescriptor(JetNamespace declaration) {
return (NamespaceDescriptor) declarationsToDescriptors.get(declaration);
return namespaceDeclarationsToDescriptors.get(declaration);
}
@Override
@@ -136,10 +146,16 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
}
@Override
public VariableDescriptor getParameterDescriptor(JetParameter declaration) {
public VariableDescriptor getVariableDescriptor(JetParameter declaration) {
return (VariableDescriptor) declarationsToDescriptors.get(declaration);
}
@Override
public PropertyDescriptor getPropertyDescriptor(JetParameter primaryConstructorParameter) {
PropertyDescriptor descriptor = primaryConstructorParameterDeclarationsToPropertyDescriptors.get(primaryConstructorParameter);
return descriptor;
}
@Override
public JetType resolveTypeReference(JetTypeReference typeReference) {
return types.get(typeReference);
@@ -192,6 +208,12 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
@Override
public boolean hasBackingField(@NotNull PropertyDescriptor propertyDescriptor) {
PsiElement declarationPsiElement = getDeclarationPsiElement(propertyDescriptor);
if (declarationPsiElement instanceof JetParameter) {
JetParameter jetParameter = (JetParameter) declarationPsiElement;
return jetParameter.getValOrVarNode() != null ||
backingFieldRequired.contains(propertyDescriptor);
}
if (propertyDescriptor.getModifiers().isAbstract()) return false;
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
@@ -509,7 +509,7 @@ public class ClassDescriptorResolver {
isMutable ? type : null,
type);
propertyDescriptor.initialize(null, null);
trace.recordDeclarationResolution(parameter, propertyDescriptor);
trace.recordValueParameterAsPropertyResolution(parameter, propertyDescriptor);
return propertyDescriptor;
}
@@ -51,6 +51,10 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@NotNull
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size();
assert unsubstitutedMemberScope != null;
if (typeArguments.isEmpty()) return unsubstitutedMemberScope;
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments);
return new SubstitutingScope(unsubstitutedMemberScope, TypeSubstitutor.create(substitutionContext));
@@ -4,7 +4,6 @@ import com.google.common.collect.Maps;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.WritableFunctionGroup;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection;
@@ -20,6 +19,8 @@ public class JavaClassMembersScope implements JetScope {
private final boolean staticMembers;
private final DeclarationDescriptor containingDeclaration;
private final Map<String, FunctionGroup> functionGroups = Maps.newHashMap();
private final Map<String, VariableDescriptor> variables = Maps.newHashMap();
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
public JavaClassMembersScope(@NotNull DeclarationDescriptor classDescriptor, PsiClass psiClass, JavaSemanticServices semanticServices, boolean staticMembers) {
this.containingDeclaration = classDescriptor;
@@ -47,6 +48,16 @@ public class JavaClassMembersScope implements JetScope {
@Override
public ClassifierDescriptor getClassifier(@NotNull String name) {
ClassifierDescriptor classifierDescriptor = classifiers.get(name);
if (classifierDescriptor == null) {
classifierDescriptor = doGetClassifierDescriptor(name);
classifiers.put(name, classifierDescriptor);
}
return classifierDescriptor;
}
private ClassifierDescriptor doGetClassifierDescriptor(String name) {
// TODO : suboptimal, walk the list only once
for (PsiClass innerClass : psiClass.getAllInnerClasses()) {
if (name.equals(innerClass.getName())) {
if (innerClass.hasModifierProperty(PsiModifier.STATIC) != staticMembers) return null;
@@ -58,6 +69,15 @@ public class JavaClassMembersScope implements JetScope {
@Override
public VariableDescriptor getVariable(@NotNull String name) {
VariableDescriptor variableDescriptor = variables.get(name);
if (variableDescriptor == null) {
variableDescriptor = doGetVariable(name);
variables.put(name, variableDescriptor);
}
return variableDescriptor;
}
private VariableDescriptor doGetVariable(String name) {
PsiField field = psiClass.findFieldByName(name, true);
if (field == null) return null;
if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
@@ -93,9 +93,9 @@ public class JavaDescriptorResolver {
));
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
// UGLY HACK
supertypes.addAll(getSupertypes(psiClass));
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
// NOTE: this writes into constructors after it is remembered by the classDescriptor
PsiMethod[] psiConstructors = psiClass.getConstructors();
@@ -27,6 +27,11 @@ public interface BindingTrace {
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
}
@Override
public void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor) {
}
@Override
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
}
@@ -64,6 +69,8 @@ public interface BindingTrace {
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor);
public void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor);
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type);
public void setToplevelScope(JetScope toplevelScope);
@@ -31,6 +31,11 @@ public class BindingTraceAdapter implements BindingTrace {
originalTrace.recordDeclarationResolution(declaration, descriptor);
}
@Override
public void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor) {
originalTrace.recordValueParameterAsPropertyResolution(declaration, descriptor);
}
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
originalTrace.recordTypeResolution(typeReference, type);
}
@@ -17,6 +17,12 @@ public class DescriptorUtil {
StringBuilder stringBuilder = new StringBuilder();
declarationDescriptor.accept(
new DeclarationDescriptorVisitor<Void, StringBuilder>() {
@Override
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
builder.append("value-parameter ");
return super.visitValueParameterDescriptor(descriptor, builder);
}
@Override
public Void visitVariableDescriptor(VariableDescriptor descriptor, StringBuilder builder) {
JetType outType = descriptor.getOutType();
@@ -151,7 +151,7 @@ public class ExpectedResolveData {
}
}
assertNotNull(reference);
assertSame(
assertEquals(
"Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".",
expected, actual);
}