hasBackingField() supported in the BindingContext

This commit is contained in:
Andrey Breslav
2011-04-20 13:19:02 +04:00
parent 7dec1ce492
commit 311282b00c
17 changed files with 299 additions and 106 deletions
@@ -45,7 +45,7 @@ public class JetSemanticServices {
} }
@NotNull @NotNull
public JetTypeInferrer getTypeInferrer(BindingTrace trace, JetFlowInformationProvider flowInformationProvider) { public JetTypeInferrer getTypeInferrer(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider) {
return new JetTypeInferrer(trace, flowInformationProvider, this); return new JetTypeInferrer(trace, flowInformationProvider, this);
} }
@@ -59,4 +59,5 @@ public class JetPropertyAccessor extends JetDeclaration implements JetDeclaratio
public JetTypeReference getReturnTypeReference() { public JetTypeReference getReturnTypeReference() {
return findChildByClass(JetTypeReference.class); return findChildByClass(JetTypeReference.class);
} }
} }
@@ -27,4 +27,5 @@ public interface BindingContext {
boolean isBlock(JetFunctionLiteralExpression expression); boolean isBlock(JetFunctionLiteralExpression expression);
boolean isStatement(JetExpression expression); boolean isStatement(JetExpression expression);
boolean hasBackingField(PropertyDescriptor propertyDescriptor);
} }
@@ -13,7 +13,7 @@ import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public class BindingTraceContext extends BindingTrace implements BindingContext { public class BindingTraceContext implements BindingContext, BindingTrace {
private final Map<JetExpression, JetType> expressionTypes = new HashMap<JetExpression, JetType>(); private final Map<JetExpression, JetType> expressionTypes = new HashMap<JetExpression, JetType>();
private final Map<JetReferenceExpression, DeclarationDescriptor> resolutionResults = new HashMap<JetReferenceExpression, DeclarationDescriptor>(); private final Map<JetReferenceExpression, DeclarationDescriptor> resolutionResults = new HashMap<JetReferenceExpression, DeclarationDescriptor>();
private final Map<JetReferenceExpression, PsiElement> labelResolutionResults = new HashMap<JetReferenceExpression, PsiElement>(); private final Map<JetReferenceExpression, PsiElement> labelResolutionResults = new HashMap<JetReferenceExpression, PsiElement>();
@@ -23,6 +23,7 @@ public class BindingTraceContext extends BindingTrace implements BindingContext
private final Map<PsiElement, ConstructorDescriptor> constructorDeclarationsToDescriptors = new HashMap<PsiElement, ConstructorDescriptor>(); private final Map<PsiElement, ConstructorDescriptor> constructorDeclarationsToDescriptors = new HashMap<PsiElement, ConstructorDescriptor>();
private final Set<JetFunctionLiteralExpression> blocks = new HashSet<JetFunctionLiteralExpression>(); private final Set<JetFunctionLiteralExpression> blocks = new HashSet<JetFunctionLiteralExpression>();
private final Set<JetElement> statements = new HashSet<JetElement>(); private final Set<JetElement> statements = new HashSet<JetElement>();
private final Set<PropertyDescriptor> fieldMentionedInAccessor = new HashSet<PropertyDescriptor>();
private JetScope toplevelScope; private JetScope toplevelScope;
@@ -70,6 +71,11 @@ public class BindingTraceContext extends BindingTrace implements BindingContext
// assert oldValue == null || oldValue == value : key + ": " + oldValue + " and " + value; // assert oldValue == null || oldValue == value : key + ": " + oldValue + " and " + value;
} }
@Override
public void recordFieldAccessFromAccessor(@NotNull PropertyDescriptor propertyDescriptor) {
fieldMentionedInAccessor.add(propertyDescriptor);
}
@Override @Override
public void recordBlock(JetFunctionLiteralExpression expression) { public void recordBlock(JetFunctionLiteralExpression expression) {
blocks.add(expression); blocks.add(expression);
@@ -164,4 +170,24 @@ public class BindingTraceContext extends BindingTrace implements BindingContext
public boolean isStatement(@NotNull JetExpression expression) { public boolean isStatement(@NotNull JetExpression expression) {
return statements.contains(expression); return statements.contains(expression);
} }
@Override
public boolean hasBackingField(@NotNull PropertyDescriptor propertyDescriptor) {
if (propertyDescriptor.getModifiers().isAbstract()) return false;
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (getter == null) {
return true;
}
else if (propertyDescriptor.isVar() && setter == null) {
return true;
}
else if (setter != null && !setter.hasBody()) {
return true;
}
else if (!getter.hasBody()) {
return true;
}
return fieldMentionedInAccessor.contains(propertyDescriptor);
}
} }
@@ -19,6 +19,8 @@ import java.util.List;
*/ */
public class ClassDescriptorResolver { public class ClassDescriptorResolver {
private static final MemberModifiers DEFAULT_MODIFIERS = new MemberModifiers(false, false, false);
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
private final TypeResolver typeResolver; private final TypeResolver typeResolver;
private final BindingTrace trace; private final BindingTrace trace;
@@ -321,23 +323,37 @@ public class ClassDescriptorResolver {
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) {
JetType type = getType(scope, property); JetType type = getType(scope, property);
boolean isVar = property.isVar();
JetModifierList modifierList = property.getModifierList();
PropertyDescriptor propertyDescriptor = new PropertyDescriptor( PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration, containingDeclaration,
AttributeResolver.INSTANCE.resolveAttributes(property.getModifierList()), AttributeResolver.INSTANCE.resolveAttributes(modifierList),
resolveModifiers(modifierList, DEFAULT_MODIFIERS), // TODO : default modifiers differ in different contexts
isVar,
JetPsiUtil.safeName(property.getName()), JetPsiUtil.safeName(property.getName()),
property.isVar() ? type : null, isVar ? type : null,
type); type);
propertyDescriptor.initialize( propertyDescriptor.initialize(
resolvePropertyGetterDescriptor(scope, property, propertyDescriptor), resolvePropertyGetterDescriptor(scope, property, propertyDescriptor),
resolvePropertySetterDescriptors(scope, property, propertyDescriptor)); resolvePropertySetterDescriptor(scope, property, propertyDescriptor));
trace.recordDeclarationResolution(property, propertyDescriptor); trace.recordDeclarationResolution(property, propertyDescriptor);
return propertyDescriptor; return propertyDescriptor;
} }
@NotNull
private MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) {
if (modifierList == null) return defaultModifiers;
return new MemberModifiers(
modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD),
modifierList.hasModifier(JetTokens.VIRTUAL_KEYWORD),
modifierList.hasModifier(JetTokens.OVERRIDE_KEYWORD)
);
}
@Nullable @Nullable
private PropertySetterDescriptor resolvePropertySetterDescriptors(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { private PropertySetterDescriptor resolvePropertySetterDescriptor(@NotNull JetScope scope, @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) {
JetPropertyAccessor setter = property.getSetter(); JetPropertyAccessor setter = property.getSetter();
if (setter != null && !property.isVar()) { if (setter != null && !property.isVar()) {
semanticServices.getErrorHandler().genericError(setter.asElement().getNode(), "A 'val'-property cannot have a setter"); semanticServices.getErrorHandler().genericError(setter.asElement().getNode(), "A 'val'-property cannot have a setter");
@@ -348,7 +364,7 @@ public class ClassDescriptorResolver {
List<Attribute> attributes = AttributeResolver.INSTANCE.resolveAttributes(setter.getModifierList()); List<Attribute> attributes = AttributeResolver.INSTANCE.resolveAttributes(setter.getModifierList());
JetParameter parameter = setter.getParameter(); JetParameter parameter = setter.getParameter();
setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, attributes); setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, attributes, setter.getBodyExpression() != null);
if (parameter != null) { if (parameter != null) {
if (parameter.isRef()) { if (parameter.isRef()) {
semanticServices.getErrorHandler().genericError(parameter.getRefNode(), "Setter parameters can not be 'ref'"); semanticServices.getErrorHandler().genericError(parameter.getRefNode(), "Setter parameters can not be 'ref'");
@@ -399,7 +415,7 @@ public class ClassDescriptorResolver {
returnType = typeResolver.resolveType(scope, returnTypeReference); returnType = typeResolver.resolveType(scope, returnTypeReference);
} }
getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, attributes, returnType); getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, attributes, returnType, getter.getBodyExpression() != null);
trace.recordDeclarationResolution(getter, getterDescriptor); trace.recordDeclarationResolution(getter, getterDescriptor);
} }
return getterDescriptor; return getterDescriptor;
@@ -479,12 +495,17 @@ public class ClassDescriptorResolver {
@NotNull JetParameter parameter) { @NotNull JetParameter parameter) {
JetType type = resolveParameterType(scope, parameter); JetType type = resolveParameterType(scope, parameter);
String name = parameter.getName(); String name = parameter.getName();
VariableDescriptorImpl propertyDescriptor = new PropertyDescriptor( boolean isMutable = parameter.isMutable();
JetModifierList modifierList = parameter.getModifierList();
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
classDescriptor, classDescriptor,
AttributeResolver.INSTANCE.resolveAttributes(parameter.getModifierList()), AttributeResolver.INSTANCE.resolveAttributes(modifierList),
resolveModifiers(modifierList, DEFAULT_MODIFIERS),
isMutable,
name == null ? "<no name>" : name, name == null ? "<no name>" : name,
parameter.isMutable() ? type : null, isMutable ? type : null,
type); type);
propertyDescriptor.initialize(null, null);
trace.recordDeclarationResolution(parameter, propertyDescriptor); trace.recordDeclarationResolution(parameter, propertyDescriptor);
return propertyDescriptor; return propertyDescriptor;
} }
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*; import java.util.*;
@@ -267,7 +268,7 @@ public class TopDownAnalyzer {
JetExpression bodyExpression = declarationWithBody.getBodyExpression(); JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (declaration instanceof JetFunction) { if (declaration instanceof JetFunction) {
resolveFunctionBody((JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope); resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope);
} }
else if (declaration instanceof JetConstructor) { else if (declaration instanceof JetConstructor) {
if (bodyExpression != null) { if (bodyExpression != null) {
@@ -283,7 +284,7 @@ public class TopDownAnalyzer {
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) { for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
JetProperty declaration = entry.getKey(); JetProperty declaration = entry.getKey();
PropertyDescriptor descriptor = entry.getValue(); final PropertyDescriptor propertyDescriptor = entry.getValue();
WritableScope declaringScope = declaringScopes.get(declaration); WritableScope declaringScope = declaringScopes.get(declaration);
JetExpression initializer = declaration.getInitializer(); JetExpression initializer = declaration.getInitializer();
@@ -294,22 +295,40 @@ public class TopDownAnalyzer {
// TODO : check type // TODO : check type
} }
BindingTraceAdapter fieldAccessTrackingTrace = new BindingTraceAdapter(trace) {
@Override
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
super.recordReferenceResolution(expression, descriptor);
if (expression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
&& descriptor == propertyDescriptor) { // TODO : original?
recordFieldAccessFromAccessor(propertyDescriptor);
}
}
}
};
JetPropertyAccessor getter = declaration.getGetter(); JetPropertyAccessor getter = declaration.getGetter();
PropertyGetterDescriptor getterDescriptor = descriptor.getGetter(); PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
if (getter != null && getterDescriptor != null) { if (getter != null && getterDescriptor != null) {
resolveFunctionBody(getter, getterDescriptor, declaringScope); resolveFunctionBody(fieldAccessTrackingTrace, getter, getterDescriptor, declaringScope);
} }
JetPropertyAccessor setter = declaration.getSetter(); JetPropertyAccessor setter = declaration.getSetter();
PropertySetterDescriptor setterDescriptor = descriptor.getSetter(); PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
if (setter != null && setterDescriptor != null) { if (setter != null && setterDescriptor != null) {
resolveFunctionBody(setter, setterDescriptor, declaringScope); resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, declaringScope);
} }
} }
} }
private void resolveFunctionBody(@NotNull JetDeclarationWithBody function, @NotNull MutableFunctionDescriptor functionDescriptor, @NotNull WritableScope declaringScope) { private void resolveFunctionBody(
@NotNull BindingTrace trace,
@NotNull JetDeclarationWithBody function,
@NotNull MutableFunctionDescriptor functionDescriptor,
@NotNull WritableScope declaringScope) {
JetExpression bodyExpression = function.getBodyExpression(); JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) { if (bodyExpression != null) {
JetFlowInformationProvider flowInformationProvider = computeFlowData(function.asElement(), bodyExpression); JetFlowInformationProvider flowInformationProvider = computeFlowData(function.asElement(), bodyExpression);
@@ -62,11 +62,14 @@ public class JavaClassMembersScope implements JetScope {
} }
JetType type = semanticServices.getTypeTransformer().transform(field.getType()); JetType type = semanticServices.getTypeTransformer().transform(field.getType());
VariableDescriptorImpl propertyDescriptor = new PropertyDescriptor( boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
containingDeclaration, containingDeclaration,
Collections.<Attribute>emptyList(), Collections.<Attribute>emptyList(),
new MemberModifiers(false, false, false),
!isFinal,
field.getName(), field.getName(),
field.hasModifierProperty(PsiModifier.FINAL) ? null : type, isFinal ? null : type,
type); type);
semanticServices.getTrace().recordDeclarationResolution(field, propertyDescriptor); semanticServices.getTrace().recordDeclarationResolution(field, propertyDescriptor);
return propertyDescriptor; return propertyDescriptor;
@@ -8,45 +8,73 @@ import org.jetbrains.jet.lang.resolve.JetScope;
/** /**
* @author abreslav * @author abreslav
*/ */
public class BindingTrace { public interface BindingTrace {
public static final BindingTrace DUMMY = new BindingTrace(); public static final BindingTrace DUMMY = new BindingTrace() {
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { @Override
} public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
}
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) { @Override
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
}
} @Override
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
}
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) { @Override
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
}
} @Override
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
}
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) { @Override
public void setToplevelScope(JetScope toplevelScope) {
}
} @Override
public void recordBlock(JetFunctionLiteralExpression expression) {
}
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) { @Override
public void recordStatement(@NotNull JetElement statement) {
}
} @Override
public void removeStatementRecord(@NotNull JetElement statement) {
}
public void setToplevelScope(JetScope toplevelScope) { @Override
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) {
}
} @Override
public void recordFieldAccessFromAccessor(@NotNull PropertyDescriptor propertyDescriptor) {
}
};
public void recordBlock(JetFunctionLiteralExpression expression) { public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type);
} public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor);
public void recordStatement(@NotNull JetElement statement) { public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element);
} public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor);
public void removeStatementRecord(@NotNull JetElement statement) { public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type);
} public void setToplevelScope(JetScope toplevelScope);
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) { public void recordBlock(JetFunctionLiteralExpression expression);
} public void recordStatement(@NotNull JetElement statement);
public void removeStatementRecord(@NotNull JetElement statement);
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression);
public void recordFieldAccessFromAccessor(@NotNull PropertyDescriptor propertyDescriptor);
} }
@@ -0,0 +1,64 @@
package org.jetbrains.jet.lang.types;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.JetScope;
/**
* @author abreslav
*/
public class BindingTraceAdapter implements BindingTrace {
private final BindingTrace originalTrace;
public BindingTraceAdapter(BindingTrace originalTrace) {
this.originalTrace = originalTrace;
}
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
originalTrace.recordExpressionType(expression, type);
}
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
originalTrace.recordReferenceResolution(expression, descriptor);
}
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
originalTrace.recordLabelResolution(expression, element);
}
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
originalTrace.recordDeclarationResolution(declaration, descriptor);
}
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
originalTrace.recordTypeResolution(typeReference, type);
}
public void setToplevelScope(JetScope toplevelScope) {
originalTrace.setToplevelScope(toplevelScope);
}
public void recordBlock(JetFunctionLiteralExpression expression) {
originalTrace.recordBlock(expression);
}
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) {
originalTrace.removeReferenceResolution(referenceExpression);
}
@Override
public void recordStatement(@NotNull JetElement statement) {
originalTrace.recordStatement(statement);
}
@Override
public void recordFieldAccessFromAccessor(@NotNull PropertyDescriptor propertyDescriptor) {
originalTrace.recordFieldAccessFromAccessor(propertyDescriptor);
}
@Override
public void removeStatementRecord(@NotNull JetElement statement) {
originalTrace.removeStatementRecord(statement);
}
}
@@ -89,7 +89,7 @@ public class ErrorUtils {
private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>"); private static final JetType ERROR_PROPERTY_TYPE = createErrorType("<ERROR PROPERTY TYPE>");
private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptor( private static final VariableDescriptor ERROR_PROPERTY = new PropertyDescriptor(
ERROR_CLASS, Collections.<Attribute>emptyList(), "<ERROR PROPERTY>", ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE); ERROR_CLASS, Collections.<Attribute>emptyList(), new MemberModifiers(false, false, false), true, "<ERROR PROPERTY>", ERROR_PROPERTY_TYPE, ERROR_PROPERTY_TYPE);
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) { private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Attribute>emptyList(), "<ERROR FUNCTION>"); FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Attribute>emptyList(), "<ERROR FUNCTION>");
@@ -440,8 +440,10 @@ public class JetTypeInferrer {
public void visitSimpleNameExpression(JetSimpleNameExpression expression) { public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
// TODO : other members // TODO : other members
// TODO : type substitutions??? // TODO : type substitutions???
if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) { String referencedName = expression.getReferencedName();
PropertyDescriptor property = scope.getPropertyByFieldReference(expression.getReferencedName()); if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
&& referencedName != null) {
PropertyDescriptor property = scope.getPropertyByFieldReference(referencedName);
if (property == null) { if (property == null) {
semanticServices.getErrorHandler().unresolvedReference(expression); semanticServices.getErrorHandler().unresolvedReference(expression);
} }
@@ -452,7 +454,6 @@ public class JetTypeInferrer {
} }
else { else {
assert expression.getReferencedNameElementType() == JetTokens.IDENTIFIER; assert expression.getReferencedNameElementType() == JetTokens.IDENTIFIER;
String referencedName = expression.getReferencedName();
if (referencedName != null) { if (referencedName != null) {
VariableDescriptor variable = scope.getVariable(referencedName); VariableDescriptor variable = scope.getVariable(referencedName);
if (variable != null) { if (variable != null) {
@@ -1566,54 +1567,16 @@ public class JetTypeInferrer {
} }
} }
private class CachedBindingTrace extends BindingTrace { private class CachedBindingTrace extends BindingTraceAdapter {
private final BindingTrace originalTrace;
public CachedBindingTrace(BindingTrace originalTrace) { public CachedBindingTrace(BindingTrace originalTrace) {
this.originalTrace = originalTrace; super(originalTrace);
} }
@Override
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
originalTrace.recordExpressionType(expression, type); super.recordExpressionType(expression, type);
typeCache.put(expression, type); typeCache.put(expression, type);
} }
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor) {
originalTrace.recordReferenceResolution(expression, descriptor);
}
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element) {
originalTrace.recordLabelResolution(expression, element);
}
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
originalTrace.recordDeclarationResolution(declaration, descriptor);
}
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type) {
originalTrace.recordTypeResolution(typeReference, type);
}
public void setToplevelScope(JetScope toplevelScope) {
originalTrace.setToplevelScope(toplevelScope);
}
public void recordBlock(JetFunctionLiteralExpression expression) {
originalTrace.recordBlock(expression);
}
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression) {
originalTrace.removeReferenceResolution(referenceExpression);
}
@Override
public void recordStatement(@NotNull JetElement statement) {
originalTrace.recordStatement(statement);
}
@Override
public void removeStatementRecord(@NotNull JetElement statement) {
originalTrace.removeStatementRecord(statement);
}
} }
} }
@@ -1,10 +1,11 @@
package org.jetbrains.jet.lang.types; package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
/** /**
* @author abreslav * @author abreslav
*/ */
public interface MemberDescriptor { public interface MemberDescriptor {
boolean isAbstract(); @NotNull
boolean isVirtual(); MemberModifiers getModifiers();
boolean isOverride();
} }
@@ -0,0 +1,33 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public class MemberModifiers {
private final boolean isAbstract;
private final boolean isVirtual;
private final boolean isOverride;
public MemberModifiers(boolean isAbstract, boolean isVirtual, boolean isOverride) {
this.isAbstract = isAbstract;
this.isVirtual = isVirtual;
this.isOverride = isOverride;
}
public boolean isAbstract() {
return isAbstract;
}
public boolean isVirtual() {
return isVirtual;
}
public boolean isOverride() {
return isOverride;
}
public boolean isOverridable() {
return isAbstract() || isVirtual() || isOverride();
}
}
@@ -10,8 +10,15 @@ import java.util.List;
*/ */
public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorImpl implements FunctionDescriptor { public abstract class PropertyAccessorDescriptor extends DeclarationDescriptorImpl implements FunctionDescriptor {
protected PropertyAccessorDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes, @NotNull String name) { private final boolean hasBody;
protected PropertyAccessorDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes, @NotNull String name, boolean hasBody) {
super(correspondingProperty.getContainingDeclaration(), attributes, name); super(correspondingProperty.getContainingDeclaration(), attributes, name);
this.hasBody = hasBody;
}
public boolean hasBody() {
return hasBody;
} }
@NotNull @NotNull
@@ -8,19 +8,40 @@ import java.util.List;
/** /**
* @author abreslav * @author abreslav
*/ */
public class PropertyDescriptor extends VariableDescriptorImpl { public class PropertyDescriptor extends VariableDescriptorImpl implements MemberDescriptor {
private final MemberModifiers memberModifiers;
private final boolean isVar;
private PropertyGetterDescriptor getter; private PropertyGetterDescriptor getter;
private PropertySetterDescriptor setter; private PropertySetterDescriptor setter;
private boolean hasBackingField;
public PropertyDescriptor( public PropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration, @NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<Attribute> attributes, @NotNull List<Attribute> attributes,
@NotNull MemberModifiers memberModifiers,
boolean isVar,
@NotNull String name, @NotNull String name,
@Nullable JetType inType, @Nullable JetType inType,
@Nullable JetType outType) { @Nullable JetType outType) {
super(containingDeclaration, attributes, name, inType, outType); super(containingDeclaration, attributes, name, inType, outType);
assert !isVar || inType != null;
assert outType != null;
this.isVar = isVar;
this.memberModifiers = memberModifiers;
}
public PropertyDescriptor(
@NotNull PropertyDescriptor original,
@Nullable JetType inType,
@Nullable JetType outType) {
this(
original.getContainingDeclaration(),
original.getAttributes(), // TODO : substitute?
original.getModifiers(),
original.isVar,
original.getName(),
inType,
outType);
} }
public void initialize(@Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) { public void initialize(@Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) {
@@ -28,6 +49,16 @@ public class PropertyDescriptor extends VariableDescriptorImpl {
this.setter = setter; this.setter = setter;
} }
public boolean isVar() {
return isVar;
}
@NotNull
@Override
public MemberModifiers getModifiers() {
return memberModifiers;
}
@Nullable @Nullable
public PropertyGetterDescriptor getGetter() { public PropertyGetterDescriptor getGetter() {
return getter; return getter;
@@ -38,23 +69,18 @@ public class PropertyDescriptor extends VariableDescriptorImpl {
return setter; return setter;
} }
public boolean hasBackingFiled() {
return hasBackingField;
}
@NotNull @NotNull
@Override @Override
public VariableDescriptor substitute(TypeSubstitutor substitutor) { public VariableDescriptor substitute(TypeSubstitutor substitutor) {
JetType originalInType = getInType(); JetType originalInType = getInType();
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE); JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
JetType outType = substitutor.substitute(getOutType(), Variance.OUT_VARIANCE); JetType originalOutType = getOutType();
JetType outType = originalOutType == null ? null : substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
if (inType == null && outType == null) { if (inType == null && outType == null) {
return null; // TODO : tell the user that the property was projected out return null; // TODO : tell the user that the property was projected out
} }
return new PropertyDescriptor( return new PropertyDescriptor(
getContainingDeclaration(), this,
getAttributes(), // TODO
getName(),
inType, inType,
outType outType
); );
@@ -12,8 +12,8 @@ import java.util.List;
public class PropertyGetterDescriptor extends PropertyAccessorDescriptor implements MutableFunctionDescriptor { public class PropertyGetterDescriptor extends PropertyAccessorDescriptor implements MutableFunctionDescriptor {
private JetType returnType; private JetType returnType;
public PropertyGetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes, @Nullable JetType returnType) { public PropertyGetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes, @Nullable JetType returnType, boolean hasBody) {
super(correspondingProperty, attributes, "get-" + correspondingProperty.getName()); super(correspondingProperty, attributes, "get-" + correspondingProperty.getName(), hasBody);
this.returnType = returnType == null ? correspondingProperty.getOutType() : returnType; this.returnType = returnType == null ? correspondingProperty.getOutType() : returnType;
} }
@@ -12,8 +12,8 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor impleme
private MutableValueParameterDescriptor parameter; private MutableValueParameterDescriptor parameter;
public PropertySetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes) { public PropertySetterDescriptor(@NotNull PropertyDescriptor correspondingProperty, @NotNull List<Attribute> attributes, boolean hasBody) {
super(correspondingProperty, attributes, "set-" + correspondingProperty.getName()); super(correspondingProperty, attributes, "set-" + correspondingProperty.getName(), hasBody);
} }
public void initialize(@NotNull MutableValueParameterDescriptor parameter) { public void initialize(@NotNull MutableValueParameterDescriptor parameter) {