KT-371 Resolve default parameters for constructors
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+15
-10
@@ -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());
|
||||
|
||||
|
||||
+24
-18
@@ -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
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -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
|
||||
Reference in New Issue
Block a user