Working on constructors: references on 'this()' calls, etc. Many checks pending
This commit is contained in:
@@ -53,6 +53,7 @@ public interface JetNodeTypes {
|
|||||||
JetNodeType PROPERTY_ACCESSOR = new JetNodeType("PROPERTY_ACCESSOR", JetPropertyAccessor.class);
|
JetNodeType PROPERTY_ACCESSOR = new JetNodeType("PROPERTY_ACCESSOR", JetPropertyAccessor.class);
|
||||||
JetNodeType INITIALIZER_LIST = new JetNodeType("INITIALIZER_LIST", JetInitializerList.class);
|
JetNodeType INITIALIZER_LIST = new JetNodeType("INITIALIZER_LIST", JetInitializerList.class);
|
||||||
JetNodeType THIS_CALL = new JetNodeType("THIS_CALL", JetDelegatorToThisCall.class);
|
JetNodeType THIS_CALL = new JetNodeType("THIS_CALL", JetDelegatorToThisCall.class);
|
||||||
|
JetNodeType THIS_CONSTRUCTOR_REFERENCE = new JetNodeType("THIS_CONSTRUCTOR_REFERENCE", JetThisReferenceExpression.class);
|
||||||
JetNodeType TYPE_CONSTRAINT_LIST = new JetNodeType("TYPE_CONSTRAINT_LIST", JetTypeConstraintList.class);
|
JetNodeType TYPE_CONSTRAINT_LIST = new JetNodeType("TYPE_CONSTRAINT_LIST", JetTypeConstraintList.class);
|
||||||
JetNodeType TYPE_CONSTRAINT = new JetNodeType("TYPE_CONSTRAINT", JetTypeConstraint.class);
|
JetNodeType TYPE_CONSTRAINT = new JetNodeType("TYPE_CONSTRAINT", JetTypeConstraint.class);
|
||||||
|
|
||||||
|
|||||||
@@ -623,7 +623,9 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
IElementType type;
|
IElementType type;
|
||||||
if (at(THIS_KEYWORD)) {
|
if (at(THIS_KEYWORD)) {
|
||||||
|
PsiBuilder.Marker mark = mark();
|
||||||
advance(); // THIS_KEYWORD
|
advance(); // THIS_KEYWORD
|
||||||
|
mark.done(THIS_CONSTRUCTOR_REFERENCE);
|
||||||
type = THIS_CALL;
|
type = THIS_CALL;
|
||||||
}
|
}
|
||||||
else if (atSet(TYPE_REF_FIRST)) {
|
else if (atSet(TYPE_REF_FIRST)) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.List;
|
|||||||
* @author max
|
* @author max
|
||||||
*/
|
*/
|
||||||
public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCall {
|
public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCall {
|
||||||
|
|
||||||
public JetDelegatorToThisCall(@NotNull ASTNode node) {
|
public JetDelegatorToThisCall(@NotNull ASTNode node) {
|
||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
@@ -37,4 +38,8 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je
|
|||||||
public List<JetExpression> getFunctionLiteralArguments() {
|
public List<JetExpression> getFunctionLiteralArguments() {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JetReferenceExpression getThisReference() {
|
||||||
|
return findChildByClass(JetThisReferenceExpression.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package org.jetbrains.jet.lang.psi;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.openapi.util.TextRange;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.PsiReference;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class JetThisReferenceExpression extends JetReferenceExpression {
|
||||||
|
public JetThisReferenceExpression(@NotNull ASTNode node) {
|
||||||
|
super(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiReference getReference() {
|
||||||
|
return new JetPsiReference() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PsiElement getElement() {
|
||||||
|
return JetThisReferenceExpression.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextRange getRangeInElement() {
|
||||||
|
return new TextRange(0, getElement().getTextLength());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -270,81 +270,61 @@ public class TopDownAnalyzer {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void resolveBehaviorDeclarationBodies() {
|
private void resolveBehaviorDeclarationBodies() {
|
||||||
|
resolveDelegationSpecifierLists();
|
||||||
|
|
||||||
|
|
||||||
|
//TODO : anonymous initializers
|
||||||
|
|
||||||
resolvePropertyDeclarationBodies();
|
resolvePropertyDeclarationBodies();
|
||||||
resolveFunctionDeclarationBodies();
|
resolveFunctionDeclarationBodies();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveFunctionDeclarationBodies() {
|
private void resolveDelegationSpecifierLists() {
|
||||||
for (Map.Entry<JetDeclaration, FunctionDescriptor> entry : functions.entrySet()) {
|
final JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.NONE);
|
||||||
JetDeclaration declaration = entry.getKey();
|
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
|
||||||
FunctionDescriptor descriptor = entry.getValue();
|
final JetClass declaration = entry.getKey();
|
||||||
|
final MutableClassDescriptor descriptor = entry.getValue();
|
||||||
|
|
||||||
WritableScope declaringScope = declaringScopes.get(declaration);
|
for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
|
||||||
assert declaringScope != null;
|
delegationSpecifier.accept(new JetVisitor() {
|
||||||
|
@Override
|
||||||
if (declaration instanceof JetFunction) {
|
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
|
||||||
resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope);
|
JetExpression delegateExpression = specifier.getDelegateExpression();
|
||||||
}
|
if (delegateExpression != null) {
|
||||||
else if (declaration instanceof JetConstructor) {
|
JetType type = typeInferrer.getType(descriptor.getWritableUnsubstitutedMemberScope(), delegateExpression, false);
|
||||||
resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope);
|
JetType supertype = trace.resolveTypeReference(specifier.getTypeReference());
|
||||||
}
|
if (type != null && !semanticServices.getTypeChecker().isSubtypeOf(type, supertype)) { // TODO : Convertible?
|
||||||
else {
|
semanticServices.getErrorHandler().typeMismatch(delegateExpression, supertype, type);
|
||||||
throw new UnsupportedOperationException(); // TODO
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert descriptor.getUnsubstitutedReturnType() != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveConstructorBody(JetConstructor declaration, FunctionDescriptor descriptor, final WritableScope declaringScope) {
|
|
||||||
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
|
|
||||||
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
|
|
||||||
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
|
||||||
}
|
|
||||||
final JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices);
|
|
||||||
final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE);
|
|
||||||
for (JetDelegationSpecifier initializer : declaration.getInitializers()) {
|
|
||||||
// TODO : check that the type being referenced is actually a supertype
|
|
||||||
initializer.accept(new JetVisitor() {
|
|
||||||
@Override
|
|
||||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
|
||||||
JetTypeReference typeReference = call.getTypeReference();
|
|
||||||
if (typeReference != null) {
|
|
||||||
typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
|
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||||
JetTypeReference typeReference = call.getTypeReference(); // TODO : use explicit type here
|
JetTypeReference typeReference = call.getTypeReference();
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call);
|
typeInferrer.checkConstructorCall(descriptor.getWritableUnsubstitutedMemberScope(), typeReference, call);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
|
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
|
||||||
semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors");
|
if (declaration.getPrimaryConstructorParameterList() != null) {
|
||||||
}
|
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required in initializer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
|
public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) {
|
||||||
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required");
|
throw new IllegalStateException("This-calls should be prohibitied by the parser");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDelegationSpecifier(JetDelegationSpecifier specifier) {
|
public void visitJetElement(JetElement elem) {
|
||||||
throw new IllegalStateException();
|
throw new UnsupportedOperationException(elem.getText() + " : " + elem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
JetExpression bodyExpression = declaration.getBodyExpression();
|
|
||||||
if (bodyExpression != null) {
|
|
||||||
computeFlowData(declaration, bodyExpression);
|
|
||||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
|
|
||||||
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
|
|
||||||
|
|
||||||
typeInferrer.getType(functionInnerScope, bodyExpression, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,6 +394,85 @@ public class TopDownAnalyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resolveFunctionDeclarationBodies() {
|
||||||
|
for (Map.Entry<JetDeclaration, FunctionDescriptor> entry : functions.entrySet()) {
|
||||||
|
JetDeclaration declaration = entry.getKey();
|
||||||
|
FunctionDescriptor descriptor = entry.getValue();
|
||||||
|
|
||||||
|
WritableScope declaringScope = declaringScopes.get(declaration);
|
||||||
|
assert declaringScope != null;
|
||||||
|
|
||||||
|
if (declaration instanceof JetFunction) {
|
||||||
|
resolveFunctionBody(trace, (JetFunction) declaration, (FunctionDescriptorImpl) descriptor, declaringScope);
|
||||||
|
}
|
||||||
|
else if (declaration instanceof JetConstructor) {
|
||||||
|
resolveConstructorBody((JetConstructor) declaration, descriptor, declaringScope);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
assert descriptor.getUnsubstitutedReturnType() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveConstructorBody(JetConstructor declaration, final FunctionDescriptor descriptor, final WritableScope declaringScope) {
|
||||||
|
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
|
||||||
|
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
|
||||||
|
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
||||||
|
}
|
||||||
|
final JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices);
|
||||||
|
final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE);
|
||||||
|
for (JetDelegationSpecifier initializer : declaration.getInitializers()) {
|
||||||
|
// TODO : check that the type being referenced is actually a supertype
|
||||||
|
initializer.accept(new JetVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||||
|
JetTypeReference typeReference = call.getTypeReference();
|
||||||
|
if (typeReference != null) {
|
||||||
|
typeInferrerForInitializers.checkConstructorCall(functionInnerScope, typeReference, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
|
||||||
|
// TODO : check that there's no recursion in this() calls
|
||||||
|
// TODO : check: if a this() call is present, no other initializers are allowed
|
||||||
|
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||||
|
typeInferrerForInitializers.checkClassConstructorCall(
|
||||||
|
functionInnerScope,
|
||||||
|
call.getThisReference(),
|
||||||
|
classDescriptor,
|
||||||
|
classDescriptor.getDefaultType(),
|
||||||
|
call);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
|
||||||
|
semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
|
||||||
|
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDelegationSpecifier(JetDelegationSpecifier specifier) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
JetExpression bodyExpression = declaration.getBodyExpression();
|
||||||
|
if (bodyExpression != null) {
|
||||||
|
computeFlowData(declaration, bodyExpression);
|
||||||
|
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
|
||||||
|
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
|
||||||
|
|
||||||
|
typeInferrer.getType(functionInnerScope, bodyExpression, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void resolveFunctionBody(
|
private void resolveFunctionBody(
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull JetDeclarationWithBody function,
|
@NotNull JetDeclarationWithBody function,
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetType getTypeForConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
|
public JetType checkConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
|
||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
if (typeElement instanceof JetUserType) {
|
if (typeElement instanceof JetUserType) {
|
||||||
JetUserType userType = (JetUserType) typeElement;
|
JetUserType userType = (JetUserType) typeElement;
|
||||||
@@ -483,50 +483,7 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
|
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
|
||||||
if (referenceExpression != null) {
|
if (referenceExpression != null) {
|
||||||
// When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
|
return checkClassConstructorCall(scope, referenceExpression, classDescriptor, receiverType, call);
|
||||||
// of 'Array<T>' must be created anyway.
|
|
||||||
// Thus, we should either prohibit projections in type arguments in such contexts,
|
|
||||||
// or treat them as an automatic upcast to the desired type, i.e. for the user not
|
|
||||||
// to be forced to write
|
|
||||||
// val a : Array<in T> = new Array<T>(...)
|
|
||||||
// NOTE: Array may be a bad example here, some classes may have substantial functionality
|
|
||||||
// not involving their type parameters
|
|
||||||
//
|
|
||||||
// The code below upcasts the type automatically
|
|
||||||
|
|
||||||
List<TypeProjection> typeArguments = receiverType.getArguments();
|
|
||||||
|
|
||||||
List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
|
|
||||||
for (TypeProjection typeArgument : typeArguments) {
|
|
||||||
if (typeArgument.getProjectionKind() != Variance.INVARIANT) {
|
|
||||||
projectionsStripped.add(new TypeProjection(typeArgument.getType()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
projectionsStripped.add(typeArgument);
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
|
|
||||||
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
|
|
||||||
JetType constructorReturnedType = resolveOverloads(
|
|
||||||
scope,
|
|
||||||
wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
|
|
||||||
Collections.<JetTypeProjection>emptyList(),
|
|
||||||
call.getValueArguments(),
|
|
||||||
call.getFunctionLiteralArguments());
|
|
||||||
if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
|
|
||||||
trace.recordReferenceResolution(referenceExpression, receiverType.getConstructor().getDeclarationDescriptor());
|
|
||||||
// TODO : more helpful message
|
|
||||||
JetArgumentList argumentList = call.getValueArgumentList();
|
|
||||||
if (argumentList != null) {
|
|
||||||
semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
|
|
||||||
}
|
|
||||||
constructorReturnedType = receiverType;
|
|
||||||
}
|
|
||||||
// If no upcast needed:
|
|
||||||
return constructorReturnedType;
|
|
||||||
|
|
||||||
// Automatic upcast:
|
|
||||||
// result = receiverType;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -541,6 +498,61 @@ public class JetTypeInferrer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public JetType checkClassConstructorCall(
|
||||||
|
@NotNull JetScope scope,
|
||||||
|
@NotNull JetReferenceExpression referenceExpression,
|
||||||
|
@NotNull ClassDescriptor classDescriptor,
|
||||||
|
@NotNull JetType receiverType,
|
||||||
|
@NotNull JetCall call) {
|
||||||
|
// When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
|
||||||
|
// of 'Array<T>' must be created anyway.
|
||||||
|
// Thus, we should either prohibit projections in type arguments in such contexts,
|
||||||
|
// or treat them as an automatic upcast to the desired type, i.e. for the user not
|
||||||
|
// to be forced to write
|
||||||
|
// val a : Array<in T> = new Array<T>(...)
|
||||||
|
// NOTE: Array may be a bad example here, some classes may have substantial functionality
|
||||||
|
// not involving their type parameters
|
||||||
|
//
|
||||||
|
// The code below upcasts the type automatically
|
||||||
|
|
||||||
|
List<TypeProjection> typeArguments = receiverType.getArguments();
|
||||||
|
|
||||||
|
List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
|
||||||
|
for (TypeProjection typeArgument : typeArguments) {
|
||||||
|
if (typeArgument.getProjectionKind() != Variance.INVARIANT) {
|
||||||
|
projectionsStripped.add(new TypeProjection(typeArgument.getType()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
projectionsStripped.add(typeArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
|
||||||
|
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
|
||||||
|
JetType constructorReturnedType = resolveOverloads(
|
||||||
|
scope,
|
||||||
|
wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
|
||||||
|
Collections.<JetTypeProjection>emptyList(),
|
||||||
|
call.getValueArguments(),
|
||||||
|
call.getFunctionLiteralArguments());
|
||||||
|
if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
|
||||||
|
DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
|
||||||
|
assert declarationDescriptor != null;
|
||||||
|
trace.recordReferenceResolution(referenceExpression, declarationDescriptor);
|
||||||
|
// TODO : more helpful message
|
||||||
|
JetArgumentList argumentList = call.getValueArgumentList();
|
||||||
|
if (argumentList != null) {
|
||||||
|
semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
|
||||||
|
}
|
||||||
|
constructorReturnedType = receiverType;
|
||||||
|
}
|
||||||
|
// If no upcast needed:
|
||||||
|
return constructorReturnedType;
|
||||||
|
|
||||||
|
// Automatic upcast:
|
||||||
|
// result = receiverType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -1133,7 +1145,7 @@ public class JetTypeInferrer {
|
|||||||
// TODO : type argument inference
|
// TODO : type argument inference
|
||||||
JetTypeReference typeReference = expression.getTypeReference();
|
JetTypeReference typeReference = expression.getTypeReference();
|
||||||
if (typeReference != null) {
|
if (typeReference != null) {
|
||||||
result = getTypeForConstructorCall(scope, typeReference, expression);
|
result = checkConstructorCall(scope, typeReference, expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class Z {
|
||||||
|
this() : this(1, true) {}
|
||||||
|
|
||||||
|
this(x : Int, y : Boolean) : this<error>(1)</error> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo() : <error>Z</error>, <error>this</error>() {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,8 @@ JetFile: Constructors.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
@@ -78,7 +79,8 @@ JetFile: Constructors.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
|
|||||||
@@ -101,7 +101,8 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
@@ -343,7 +344,8 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
@@ -428,7 +430,8 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
@@ -477,7 +480,8 @@ JetFile: SimpleClassMembers.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ JetFile: SimpleClassMembers_ERR.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
@@ -141,7 +142,8 @@ JetFile: SimpleClassMembers_ERR.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
|
|||||||
@@ -210,7 +210,8 @@ JetFile: BinaryTree.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
|
|||||||
@@ -975,7 +975,8 @@ JetFile: HashMap.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
INITIALIZER_LIST
|
INITIALIZER_LIST
|
||||||
THIS_CALL
|
THIS_CALL
|
||||||
PsiElement(this)('this')
|
THIS_CONSTRUCTOR_REFERENCE
|
||||||
|
PsiElement(this)('this')
|
||||||
VALUE_ARGUMENT_LIST
|
VALUE_ARGUMENT_LIST
|
||||||
PsiElement(LPAR)('(')
|
PsiElement(LPAR)('(')
|
||||||
VALUE_ARGUMENT
|
VALUE_ARGUMENT
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
class Z {
|
||||||
|
~c1~this() : `c2`this(1, true) {}
|
||||||
|
|
||||||
|
~c2~this(x : Int, y : Boolean) : `c1`this() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Z1.c()~class Z1() : Z {
|
||||||
|
|
||||||
|
this(x : Int, y : Boolean) : `Z1.c()`this() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo
|
||||||
@@ -143,4 +143,8 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
|||||||
doTest("/resolve/Classifiers.jet", true, true);
|
doTest("/resolve/Classifiers.jet", true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testConstructorsAndInitializers() throws Exception {
|
||||||
|
doTest("/resolve/ConstructorsAndInitializers.jet", true, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user