KT-371 Resolve default parameters for constructors

This commit is contained in:
svtk
2011-12-08 18:29:52 +04:00
parent a0cd4af3bd
commit d93818d0f5
10 changed files with 109 additions and 42 deletions
@@ -574,7 +574,11 @@ public class JetControlFlowProcessor {
@Override
public void visitParameter(JetParameter parameter) {
JetExpression defaultValue = parameter.getDefaultValue();
builder.declare(parameter);
if (defaultValue != null) {
builder.read(defaultValue);
}
builder.write(parameter, parameter);
}
@@ -838,6 +842,10 @@ public class JetControlFlowProcessor {
@Override
public void visitClass(JetClass klass) {
List<JetParameter> parameters = klass.getPrimaryConstructorParameters();
for (JetParameter parameter : parameters) {
value(parameter, inCondition);
}
visitClassOrObject(klass);
}
@@ -262,7 +262,12 @@ public class JetFlowInformationProvider {
}
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
varWithUninitializedErrorGenerated.add(variableDescriptor);
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
if (variableDescriptor instanceof ValueParameterDescriptor) {
trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, (ValueParameterDescriptor) variableDescriptor));
}
else {
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
}
}
}
@@ -261,6 +261,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
propertyDescriptor,
Lists.newArrayList(setter.getAnnotations()),
setter.hasBody(), setter.isDefault());
if (newSetter != null) {
newSetter.initialize(setter.getValueParameters().get(0).copy(newSetter));
}
propertyDescriptor.initialize(newGetter, newSetter);
return propertyDescriptor;
}
@@ -1,6 +1,5 @@
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
@@ -15,22 +14,28 @@ import java.util.Set;
*/
public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
private MutableValueParameterDescriptor parameter;
private ValueParameterDescriptor parameter;
public PropertySetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility,
@NotNull PropertyDescriptor correspondingProperty, @NotNull List<AnnotationDescriptor> annotations,
boolean hasBody, boolean isDefault)
{
public PropertySetterDescriptor(@NotNull Modality modality,
@NotNull Visibility visibility,
@NotNull PropertyDescriptor correspondingProperty,
@NotNull List<AnnotationDescriptor> annotations,
boolean hasBody,
boolean isDefault) {
super(modality, visibility, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault);
if (isDefault) {
initializeDefault();
}
}
public void initialize(@NotNull MutableValueParameterDescriptor parameter) {
public void initialize(@NotNull ValueParameterDescriptor parameter) {
assert this.parameter == null;
this.parameter = parameter;
}
public void setParameterType(@NotNull JetType type) {
parameter.setType(type);
public void initializeDefault() {
assert parameter == null;
parameter = new ValueParameterDescriptorImpl(this, 0, Collections.<AnnotationDescriptor>emptyList(), "<>", null, getCorrespondingProperty().getReturnType(), false, null);
}
@NotNull
@@ -42,7 +47,7 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
@NotNull
@Override
public List<ValueParameterDescriptor> getValueParameters() {
return Collections.<ValueParameterDescriptor>singletonList(parameter);
return Collections.singletonList(parameter);
}
@NotNull
@@ -150,7 +150,8 @@ public interface Errors {
};
PsiElementOnlyDiagnosticFactory3<JetModifierListOwner, CallableMemberDescriptor, CallableMemberDescriptor, DeclarationDescriptor> VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME);
UnusedElementDiagnosticFactory<JetProperty, VariableDescriptor> UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME);
UnusedElementDiagnosticFactory<JetParameter, VariableDescriptor> UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, "Parameter ''{0}'' is never used", NAME);
UnusedElementDiagnosticFactory<JetNamedDeclaration, DeclarationDescriptor> ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME);
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
@@ -48,6 +49,7 @@ public class BodyResolver {
resolvePropertyDeclarationBodies();
resolveAnonymousInitializers();
resolvePrimaryConstructorParameters();
resolveSecondaryConstructorBodies();
resolveFunctionBodies();
@@ -250,6 +252,17 @@ public class BodyResolver {
}
}
private void resolvePrimaryConstructorParameters() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
JetClass klass = entry.getKey();
MutableClassDescriptor classDescriptor = entry.getValue();
ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
if (unsubstitutedPrimaryConstructor != null) {
checkDefaultParameterValues(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), classDescriptor.getScopeForInitializers());
}
}
}
private void resolveSecondaryConstructorBodies() {
for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : this.context.getConstructors().entrySet()) {
JetSecondaryConstructor constructor = entry.getKey();
@@ -332,8 +345,10 @@ public class BodyResolver {
if (bodyExpression != null) {
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
typeInferrer.checkFunctionReturnType(scopeForConstructorBody, declaration, JetStandardClasses.getUnitType());
typeInferrer.checkFunctionReturnType(scopeForConstructorBody, declaration, descriptor, JetStandardClasses.getUnitType());
}
checkDefaultParameterValues(declaration.getValueParameters(), descriptor.getValueParameters(), scopeForConstructorBody);
}
private void resolvePropertyDeclarationBodies() {
@@ -477,17 +492,25 @@ public class BodyResolver {
if (!context.completeAnalysisNeeded(function)) return;
JetExpression bodyExpression = function.getBodyExpression();
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
if (bodyExpression != null) {
//JetFlowInformationProvider flowInformationProvider = context.getDescriptorResolver().computeFlowData(function.asElement(), bodyExpression);
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor);
typeInferrer.checkFunctionReturnType(functionInnerScope, function, functionDescriptor);
}
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
List<JetParameter> valueParameters = function.getValueParameters();
List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
checkDefaultParameterValues(valueParameters, valueParameterDescriptors, functionInnerScope);
assert functionDescriptor.getReturnType() != null;
}
private void checkDefaultParameterValues(List<JetParameter> valueParameters, List<ValueParameterDescriptor> valueParameterDescriptors, JetScope declaringScope) {
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
for (int i = 0; i < valueParameters.size(); i++) {
ValueParameterDescriptor valueParameterDescriptor = functionDescriptor.getValueParameters().get(i);
ValueParameterDescriptor valueParameterDescriptor = valueParameterDescriptors.get(i);
if (valueParameterDescriptor.hasDefaultValue()) {
JetParameter jetParameter = valueParameters.get(i);
JetExpression defaultValue = jetParameter.getDefaultValue();
@@ -496,8 +519,6 @@ public class BodyResolver {
}
}
}
assert functionDescriptor.getReturnType() != null;
}
private void computeDeferredTypes() {
@@ -707,6 +707,10 @@ public class DescriptorResolver {
MutableValueParameterDescriptor valueParameterDescriptor = resolveValueParameterDescriptor(setterDescriptor, parameter, 0, type);
setterDescriptor.initialize(valueParameterDescriptor);
}
else {
setterDescriptor.initializeDefault();
}
trace.record(BindingContext.PROPERTY_ACCESSOR, setter, setterDescriptor);
}
else if (property.isVar()) {
@@ -841,11 +845,12 @@ public class DescriptorResolver {
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
name == null ? "<no name>" : name
);
JetType inType = isMutable ? type : null;
propertyDescriptor.setType(inType, type, Collections.<TypeParameterDescriptor>emptyList(), ReceiverDescriptor.NO_RECEIVER);
PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor);
PropertySetterDescriptor setter = createDefaultSetter(propertyDescriptor);
JetType inType = isMutable ? type : null;
propertyDescriptor.setType(inType, type, Collections.<TypeParameterDescriptor>emptyList(), ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.initialize(getter, setter);
getter.initialize(propertyDescriptor.getOutType());
@@ -18,13 +18,17 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.CommonSupertypes;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT;
import static org.jetbrains.jet.lang.types.TypeUtils.FORBIDDEN;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -76,10 +80,6 @@ public class ExpressionTypingServices {
// return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE));
}
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.EMPTY);
}
@NotNull
public JetType inferFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
Map<JetExpression, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor);
@@ -89,24 +89,30 @@ public class ExpressionTypingServices {
: CommonSupertypes.commonSupertype(types);
}
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType) {
checkFunctionReturnType(function, ExpressionTypingContext.newContext(
semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, expectedReturnType, false
));
public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, null);
}
public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @Nullable JetType expectedReturnType) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, expectedReturnType);
}
/////////////////////////////////////////////////////////
/*package*/ void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, DataFlowInfo dataFlowInfo) {
JetType expectedReturnType = functionDescriptor.getReturnType();
if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
expectedReturnType = NO_EXPECTED_TYPE;
/*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, dataFlowInfo, null);
}
/*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedReturnType) {
if (expectedReturnType == null) {
expectedReturnType = functionDescriptor.getReturnType();
if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
expectedReturnType = NO_EXPECTED_TYPE;
}
}
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
checkFunctionReturnType(function, ExpressionTypingContext.newContext(
semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType, false
semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType, false
));
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.types.expressions;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,6 +13,7 @@ import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.types.JetStandardClasses;
@@ -108,7 +110,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
public JetType visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
FunctionDescriptorImpl functionDescriptor = context.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function);
scope.addFunctionDescriptor(functionDescriptor);
context.getServices().checkFunctionReturnType(context.scope, function, functionDescriptor, context.dataFlowInfo);
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
context.getServices().checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo);
return checkExpectedType(function, context);
}
@@ -1,5 +1,15 @@
val x = ""
fun bar(<!UNUSED_PARAMETER!>x<!> : Int = <!TYPE_MISMATCH!>""<!>, <!UNUSED_PARAMETER!>y<!> : Int = <!TYPE_MISMATCH!>x<!>, <!UNUSED_PARAMETER!>z<!> : String = <!UNRESOLVED_REFERENCE!>y<!>) {
fun bar(x : Int = <!TYPE_MISMATCH!>""<!>, y : Int = x, <!UNUSED_PARAMETER!>z<!> : String = <!TYPE_MISMATCH!>y<!>) {
}
}
// KT-371 Resolve default parameters for constructors
class A(x : Int = <!UNINITIALIZED_PARAMETER!>y<!>, y : Int = x) { // None of the references is resolved, no types checked
this(bool: Boolean, a: Int = <!TYPE_MISMATCH, UNINITIALIZED_PARAMETER!>b<!>, b: String = <!TYPE_MISMATCH!>a<!>) : this(1) {}
}
val z = 3
fun foo(x: Int = <!UNINITIALIZED_PARAMETER!>y<!>, y: Int = x, <!UNUSED_PARAMETER!>i<!> : Int = z): Int = x + y