$field is accessible from constructors

This commit is contained in:
Andrey Breslav
2011-04-21 13:05:53 +04:00
parent ca579e25b7
commit 225b81f626
2 changed files with 55 additions and 19 deletions
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor; import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
@@ -21,25 +23,38 @@ public class TopDownAnalyzer {
private final Map<JetDeclaration, FunctionDescriptor> functions = new LinkedHashMap<JetDeclaration, FunctionDescriptor>(); private final Map<JetDeclaration, FunctionDescriptor> functions = new LinkedHashMap<JetDeclaration, FunctionDescriptor>();
private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>(); private final Map<JetProperty, PropertyDescriptor> properties = new LinkedHashMap<JetProperty, PropertyDescriptor>();
private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>(); private final Map<JetDeclaration, WritableScope> declaringScopes = new HashMap<JetDeclaration, WritableScope>();
private final Multimap<DeclarationDescriptor, PropertyDescriptor> declaringScopesToProperties = ArrayListMultimap.create();
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
private final ClassDescriptorResolver classDescriptorResolver; private final ClassDescriptorResolver classDescriptorResolver;
private final BindingTrace trace; private final BindingTraceContext trace;
private final JetControlFlowDataTraceFactory flowDataTraceFactory; private final JetControlFlowDataTraceFactory flowDataTraceFactory;
private boolean readyToProcessExpressions = false; private boolean readyToProcessExpressions = false;
private final BindingTraceAdapter traceForConstructors;
public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTrace bindingTrace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTraceContext bindingTrace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, bindingTrace); this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, bindingTrace);
this.trace = bindingTrace; this.trace = bindingTrace;
this.flowDataTraceFactory = flowDataTraceFactory; this.flowDataTraceFactory = flowDataTraceFactory;
this.traceForConstructors = 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) {
if (!trace.hasBackingField((PropertyDescriptor) descriptor)) {
TopDownAnalyzer.this.semanticServices.getErrorHandler().genericError(expression.getNode(), "This property does not have a backing field");
}
}
}
}
};
} }
public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTrace bindingTrace) { public TopDownAnalyzer(JetSemanticServices semanticServices, @NotNull BindingTraceContext bindingTrace) {
this.semanticServices = semanticServices; this(semanticServices, bindingTrace, JetControlFlowDataTraceFactory.EMPTY);
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, bindingTrace);
this.trace = bindingTrace;
this.flowDataTraceFactory = JetControlFlowDataTraceFactory.EMPTY;
} }
public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) { public void process(@NotNull JetScope outerScope, @NotNull JetDeclaration declaration) {
@@ -244,6 +259,7 @@ public class TopDownAnalyzer {
declaringScopes.put(property, declaringScope); declaringScopes.put(property, declaringScope);
PropertyDescriptor descriptor = classDescriptorResolver.resolvePropertyDescriptor(declaringScope.getContainingDeclaration(), declaringScope, property); PropertyDescriptor descriptor = classDescriptorResolver.resolvePropertyDescriptor(declaringScope.getContainingDeclaration(), declaringScope, property);
declaringScope.addVariableDescriptor(descriptor); declaringScope.addVariableDescriptor(descriptor);
declaringScopesToProperties.put(declaringScope.getContainingDeclaration(), descriptor);
properties.put(property, descriptor); properties.put(property, descriptor);
} }
@@ -254,6 +270,11 @@ public class TopDownAnalyzer {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void resolveBehaviorDeclarationBodies() { private void resolveBehaviorDeclarationBodies() {
resolvePropertyDeclarationBodies();
resolveFunctionDeclarationBodies();
}
private void resolveFunctionDeclarationBodies() {
for (Map.Entry<JetDeclaration, FunctionDescriptor> entry : functions.entrySet()) { for (Map.Entry<JetDeclaration, FunctionDescriptor> entry : functions.entrySet()) {
JetDeclaration declaration = entry.getKey(); JetDeclaration declaration = entry.getKey();
FunctionDescriptor descriptor = entry.getValue(); FunctionDescriptor descriptor = entry.getValue();
@@ -261,26 +282,36 @@ public class TopDownAnalyzer {
WritableScope declaringScope = declaringScopes.get(declaration); WritableScope declaringScope = declaringScopes.get(declaration);
assert declaringScope != null; assert declaringScope != null;
assert declaration instanceof JetFunction || declaration instanceof JetConstructor;
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) declaration;
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (declaration instanceof JetFunction) { if (declaration instanceof JetFunction) {
resolveFunctionBody(trace, (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) { resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope);
computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider);
typeInferrer.getType(FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, descriptor, semanticServices), bodyExpression, true);
}
} }
else {
throw new UnsupportedOperationException(); // TODO
}
assert descriptor.getUnsubstitutedReturnType() != null; assert descriptor.getUnsubstitutedReturnType() != null;
} }
}
private void resolveConstructorBody(JetConstructor declaration, FunctionDescriptor descriptor, WritableScope declaringScope) {
JetExpression bodyExpression = declaration.getBodyExpression();
if (bodyExpression != null) {
computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
}
typeInferrer.getType(FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices), bodyExpression, true);
}
}
private void resolvePropertyDeclarationBodies() {
for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) { for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) {
JetProperty declaration = entry.getKey(); JetProperty declaration = entry.getKey();
final PropertyDescriptor propertyDescriptor = entry.getValue(); final PropertyDescriptor propertyDescriptor = entry.getValue();
+5
View File
@@ -14,6 +14,11 @@ class Test {
var b : Int get() = <error>$a</error>; set(x) {a = x; <error>$a</error> = x} var b : Int get() = <error>$a</error>; set(x) {a = x; <error>$a</error> = x}
this() { this() {
<error>$b</error> = $a
$a = <error>$b</error>
a = <error>$b</error>
}
fun f() {
<error>$b</error> = <error>$a</error> <error>$b</error> = <error>$a</error>
a = <error>$b</error> a = <error>$b</error>
} }