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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user