JET-84 Support generic parameter constraints for class objects
Done for classes only, not for functions
This commit is contained in:
@@ -42,6 +42,6 @@ typeParameter
|
|||||||
;
|
;
|
||||||
|
|
||||||
typeConstraint
|
typeConstraint
|
||||||
: userType ":" type
|
: attributes SimpleName ":" type
|
||||||
: "class" "object" userType ":" type
|
: attributes "class" "object" SimpleName ":" type
|
||||||
;
|
;
|
||||||
@@ -92,5 +92,15 @@ public abstract class JetDiagnostic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private final StackTraceElement[] stackTrace;
|
||||||
|
//
|
||||||
|
// protected JetDiagnostic() {
|
||||||
|
// stackTrace = Thread.currentThread().getStackTrace();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public StackTraceElement[] getStackTrace() {
|
||||||
|
// return stackTrace;
|
||||||
|
// }
|
||||||
|
|
||||||
public abstract void acceptHandler(@NonNls ErrorHandler handler);
|
public abstract void acceptHandler(@NonNls ErrorHandler handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) {
|
public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) {
|
||||||
super.initialize(null, Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
|
super.initialize(null, Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, null);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReturnType(JetType unsubstitutedReturnType) {
|
public void setReturnType(@NotNull JetType unsubstitutedReturnType) {
|
||||||
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
private final WritableScope scopeForSupertypeResolution;
|
private final WritableScope scopeForSupertypeResolution;
|
||||||
private MutableClassDescriptor classObjectDescriptor;
|
private MutableClassDescriptor classObjectDescriptor;
|
||||||
private JetType classObjectType;
|
private JetType classObjectType;
|
||||||
|
private JetType defaultType;
|
||||||
|
|
||||||
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
||||||
super(containingDeclaration);
|
super(containingDeclaration);
|
||||||
@@ -66,6 +67,9 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
public void addConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
public void addConstructor(@NotNull ConstructorDescriptor constructorDescriptor) {
|
||||||
assert constructorDescriptor.getContainingDeclaration() == this;
|
assert constructorDescriptor.getContainingDeclaration() == this;
|
||||||
constructors.addFunction(constructorDescriptor);
|
constructors.addFunction(constructorDescriptor);
|
||||||
|
if (defaultType != null) {
|
||||||
|
((ConstructorDescriptorImpl) constructorDescriptor).setReturnType(getDefaultType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -115,10 +119,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
this.typeParameters.add(typeParameterDescriptor);
|
this.typeParameters.add(typeParameterDescriptor);
|
||||||
scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
|
scopeForSupertypeResolution.addTypeParameterDescriptor(typeParameterDescriptor);
|
||||||
}
|
}
|
||||||
scopeForMemberResolution.setThisType(getDefaultType());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -138,18 +140,24 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public TypeConstructor getTypeConstructor() {
|
public TypeConstructor getTypeConstructor() {
|
||||||
if (typeConstructor == null) {
|
|
||||||
this.typeConstructor = new TypeConstructorImpl(
|
|
||||||
this,
|
|
||||||
Collections.<Annotation>emptyList(), // TODO : pass annotations from the class?
|
|
||||||
!open,
|
|
||||||
getName(),
|
|
||||||
typeParameters,
|
|
||||||
supertypes);
|
|
||||||
}
|
|
||||||
return typeConstructor;
|
return typeConstructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void createTypeConstructor() {
|
||||||
|
assert typeConstructor == null : typeConstructor;
|
||||||
|
this.typeConstructor = new TypeConstructorImpl(
|
||||||
|
this,
|
||||||
|
Collections.<Annotation>emptyList(), // TODO : pass annotations from the class?
|
||||||
|
!open,
|
||||||
|
getName(),
|
||||||
|
typeParameters,
|
||||||
|
supertypes);
|
||||||
|
scopeForMemberResolution.setThisType(getDefaultType());
|
||||||
|
for (FunctionDescriptor functionDescriptor : constructors.getFunctionDescriptors()) {
|
||||||
|
((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
|
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
|
||||||
@@ -164,7 +172,10 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public JetType getDefaultType() {
|
public JetType getDefaultType() {
|
||||||
return TypeUtils.makeUnsubstitutedType(this, scopeForMemberLookup);
|
if (defaultType == null) {
|
||||||
|
defaultType = TypeUtils.makeUnsubstitutedType(this, scopeForMemberLookup);
|
||||||
|
}
|
||||||
|
return defaultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -226,6 +237,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return DescriptorRenderer.TEXT.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
|
return DescriptorRenderer.TEXT_FOR_DEBUG.render(this) + "[" + getClass().getCanonicalName() + "@" + System.identityHashCode(this) + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.descriptors;
|
|||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetTupleType;
|
||||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.LazyScopeAdapter;
|
import org.jetbrains.jet.lang.resolve.LazyScopeAdapter;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
@@ -68,7 +69,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addUpperBound(@NotNull JetType bound) {
|
public void addUpperBound(@NotNull JetType bound) {
|
||||||
upperBounds.add(bound);
|
upperBounds.add(bound); // TODO : Duplicates?
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<JetType> getUpperBounds() {
|
public Set<JetType> getUpperBounds() {
|
||||||
@@ -93,7 +94,7 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
assert upperBounds.size() > 0;
|
assert upperBounds.size() > 0;
|
||||||
boundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
|
boundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
|
||||||
if (boundsAsType == null) {
|
if (boundsAsType == null) {
|
||||||
boundsAsType = JetStandardClasses.getNothingType(); // TODO : some error message?
|
boundsAsType = JetStandardClasses.getNothingType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return boundsAsType;
|
return boundsAsType;
|
||||||
@@ -145,6 +146,10 @@ public class TypeParameterDescriptor extends DeclarationDescriptorImpl implement
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addClassObjectBound(@NotNull JetType bound) {
|
||||||
|
classObjectUpperBounds.add(bound); // TODO : Duplicates?
|
||||||
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1170,20 +1170,25 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* typeConstraint
|
* typeConstraint
|
||||||
* : userType ":" type
|
* : attributes SimpleName ":" type
|
||||||
* : "class" "object" userType ":" type
|
* : attributes "class" "object" SimpleName ":" type
|
||||||
* ;
|
* ;
|
||||||
*/
|
*/
|
||||||
private void parseTypeConstraint() {
|
private void parseTypeConstraint() {
|
||||||
PsiBuilder.Marker constraint = mark();
|
PsiBuilder.Marker constraint = mark();
|
||||||
|
|
||||||
|
parseAttributeList();
|
||||||
|
|
||||||
if (at(CLASS_KEYWORD)) {
|
if (at(CLASS_KEYWORD)) {
|
||||||
advance(); // CLASS_KEYWORD
|
advance(); // CLASS_KEYWORD
|
||||||
|
|
||||||
expect(OBJECT_KEYWORD, "Expecting 'object'", TYPE_REF_FIRST);
|
expect(OBJECT_KEYWORD, "Expecting 'object'", TYPE_REF_FIRST);
|
||||||
|
|
||||||
}
|
}
|
||||||
parseTypeRef();
|
|
||||||
|
PsiBuilder.Marker reference = mark();
|
||||||
|
expect(IDENTIFIER, "Expecting type parameter name", TokenSet.orSet(TokenSet.create(COLON, COMMA), TYPE_REF_FIRST));
|
||||||
|
reference.done(REFERENCE_EXPRESSION);
|
||||||
|
|
||||||
expect(COLON, "Expecting ':' before the upper bound", TYPE_REF_FIRST);
|
expect(COLON, "Expecting ':' before the upper bound", TYPE_REF_FIRST);
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,12 @@ public class JetTypeConstraint extends JetElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @IfNotParsed
|
@Nullable @IfNotParsed
|
||||||
public JetTypeReference getSubjectTypeReference() {
|
public JetSimpleNameExpression getSubjectTypeParameterName() {
|
||||||
ASTNode node = getNode().getFirstChildNode();
|
return (JetSimpleNameExpression) findChildByType(JetNodeTypes.REFERENCE_EXPRESSION);
|
||||||
while (node != null) {
|
|
||||||
IElementType tt = node.getElementType();
|
|
||||||
if (tt == JetTokens.COLON) break;
|
|
||||||
if (tt == JetNodeTypes.TYPE_REFERENCE) return (JetTypeReference) node.getPsi();
|
|
||||||
node = node.getTreeNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @IfNotParsed
|
@Nullable @IfNotParsed
|
||||||
public JetTypeReference getExtendsTypeReference() {
|
public JetTypeReference getBoundTypeReference() {
|
||||||
boolean passedColon = false;
|
boolean passedColon = false;
|
||||||
ASTNode node = getNode().getFirstChildNode();
|
ASTNode node = getNode().getFirstChildNode();
|
||||||
while (node != null) {
|
while (node != null) {
|
||||||
|
|||||||
@@ -21,6 +21,19 @@ public class JetTypeParameterListOwner extends JetNamedDeclaration {
|
|||||||
return (JetTypeParameterList) findChildByType(JetNodeTypes.TYPE_PARAMETER_LIST);
|
return (JetTypeParameterList) findChildByType(JetNodeTypes.TYPE_PARAMETER_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public List<JetTypeConstraint> getTypeConstaints() {
|
||||||
|
JetTypeParameterList typeParameterList = getTypeParameterList();
|
||||||
|
if (typeParameterList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
JetTypeConstraintList typeConstraintList = typeParameterList.getTypeConstraintList();
|
||||||
|
if (typeConstraintList == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return typeConstraintList.getConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<JetTypeParameter> getTypeParameters() {
|
public List<JetTypeParameter> getTypeParameters() {
|
||||||
JetTypeParameterList list = getTypeParameterList();
|
JetTypeParameterList list = getTypeParameterList();
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
@@ -134,9 +136,11 @@ public class ClassDescriptorResolver {
|
|||||||
public void resolveGenericBounds(@NotNull JetClass jetClass, @NotNull MutableClassDescriptor classDescriptor) {
|
public void resolveGenericBounds(@NotNull JetClass jetClass, @NotNull MutableClassDescriptor classDescriptor) {
|
||||||
List<JetTypeParameter> typeParameters = jetClass.getTypeParameters();
|
List<JetTypeParameter> typeParameters = jetClass.getTypeParameters();
|
||||||
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
|
List<TypeParameterDescriptor> parameters = classDescriptor.getTypeConstructor().getParameters();
|
||||||
|
Map<String, TypeParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||||
JetTypeParameter jetTypeParameter = typeParameters.get(i);
|
JetTypeParameter jetTypeParameter = typeParameters.get(i);
|
||||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||||
|
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
|
||||||
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
||||||
if (extendsBound != null) {
|
if (extendsBound != null) {
|
||||||
typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getScopeForSupertypeResolution(), extendsBound));
|
typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getScopeForSupertypeResolution(), extendsBound));
|
||||||
@@ -145,7 +149,48 @@ public class ClassDescriptorResolver {
|
|||||||
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
|
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO : Bounds from with
|
for (JetTypeConstraint constraint : jetClass.getTypeConstaints()) {
|
||||||
|
JetSimpleNameExpression subjectTypeParameterName = constraint.getSubjectTypeParameterName();
|
||||||
|
if (subjectTypeParameterName == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String referencedName = subjectTypeParameterName.getReferencedName();
|
||||||
|
if (referencedName == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
|
||||||
|
if (typeParameterDescriptor == null) {
|
||||||
|
// To tell the user that we look only for locally defined type parameters
|
||||||
|
ClassifierDescriptor classifier = classDescriptor.getScopeForSupertypeResolution().getClassifier(referencedName);
|
||||||
|
if (classifier != null) {
|
||||||
|
trace.getErrorHandler().genericError(subjectTypeParameterName.getNode(), referencedName + " does not refer to a type parameter of class " + classDescriptor.getName());
|
||||||
|
trace.recordReferenceResolution(subjectTypeParameterName, classifier);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.getErrorHandler().unresolvedReference(subjectTypeParameterName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
||||||
|
if (boundTypeReference != null) {
|
||||||
|
JetType bound = typeResolverNotCheckingBounds.resolveType(classDescriptor.getScopeForSupertypeResolution(), boundTypeReference);
|
||||||
|
if (constraint.isClassObjectContraint()) {
|
||||||
|
typeParameterDescriptor.addClassObjectBound(bound);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
typeParameterDescriptor.addUpperBound(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (TypeParameterDescriptor parameter : parameters) {
|
||||||
|
if (JetStandardClasses.isNothing(parameter.getBoundsAsType())) {
|
||||||
|
PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier();
|
||||||
|
if (nameIdentifier != null) {
|
||||||
|
trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Upper bounds of " + parameter.getName() + " have empty intersection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveSupertypes(@NotNull JetClassOrObject jetClass, @NotNull MutableClassDescriptor descriptor) {
|
public void resolveSupertypes(@NotNull JetClassOrObject jetClass, @NotNull MutableClassDescriptor descriptor) {
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ public interface JetScope {
|
|||||||
public DeclarationDescriptor getContainingDeclaration() {
|
public DeclarationDescriptor getContainingDeclaration() {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "EMPTY";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -298,6 +298,11 @@ public class TopDownAnalyzer {
|
|||||||
JetClass jetClass = entry.getKey();
|
JetClass jetClass = entry.getKey();
|
||||||
MutableClassDescriptor descriptor = entry.getValue();
|
MutableClassDescriptor descriptor = entry.getValue();
|
||||||
classDescriptorResolver.resolveMutableClassDescriptor(jetClass, descriptor);
|
classDescriptorResolver.resolveMutableClassDescriptor(jetClass, descriptor);
|
||||||
|
descriptor.createTypeConstructor();
|
||||||
|
}
|
||||||
|
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : objects.entrySet()) {
|
||||||
|
MutableClassDescriptor descriptor = entry.getValue();
|
||||||
|
descriptor.createTypeConstructor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,8 +444,6 @@ public class TopDownAnalyzer {
|
|||||||
checkIfPrimaryConstructorIsNecessary();
|
checkIfPrimaryConstructorIsNecessary();
|
||||||
|
|
||||||
bindOverrides();
|
bindOverrides();
|
||||||
|
|
||||||
checkGenericBoundsInClassHeaders();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindOverrides() {
|
private void bindOverrides() {
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ public class TypeResolver {
|
|||||||
typeParameterDescriptor.getTypeConstructor(),
|
typeParameterDescriptor.getTypeConstructor(),
|
||||||
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
|
nullable || TypeUtils.hasNullableBound(typeParameterDescriptor),
|
||||||
Collections.<TypeProjection>emptyList(),
|
Collections.<TypeProjection>emptyList(),
|
||||||
// TODO : joint domain
|
getScopeForTypeParameter(typeParameterDescriptor)
|
||||||
JetStandardClasses.STUB
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (classifierDescriptor instanceof ClassDescriptor) {
|
else if (classifierDescriptor instanceof ClassDescriptor) {
|
||||||
@@ -160,6 +159,20 @@ public class TypeResolver {
|
|||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JetScope getScopeForTypeParameter(final TypeParameterDescriptor typeParameterDescriptor) {
|
||||||
|
if (checkBounds) {
|
||||||
|
return typeParameterDescriptor.getBoundsAsType().getMemberScope();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new LazyScopeAdapter(new LazyValue<JetScope>() {
|
||||||
|
@Override
|
||||||
|
protected JetScope compute() {
|
||||||
|
return typeParameterDescriptor.getBoundsAsType().getMemberScope();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private List<JetType> resolveTypes(JetScope scope, List<JetTypeReference> argumentElements) {
|
private List<JetType> resolveTypes(JetScope scope, List<JetTypeReference> argumentElements) {
|
||||||
final List<JetType> arguments = new ArrayList<JetType>();
|
final List<JetType> arguments = new ArrayList<JetType>();
|
||||||
for (JetTypeReference argumentElement : argumentElements) {
|
for (JetTypeReference argumentElement : argumentElements) {
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ public class JavaDescriptorResolver {
|
|||||||
Collections.<Annotation>emptyList(),
|
Collections.<Annotation>emptyList(),
|
||||||
false);
|
false);
|
||||||
constructorDescriptor.initialize(Collections.<ValueParameterDescriptor>emptyList());
|
constructorDescriptor.initialize(Collections.<ValueParameterDescriptor>emptyList());
|
||||||
|
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||||
classDescriptor.addConstructor(constructorDescriptor);
|
classDescriptor.addConstructor(constructorDescriptor);
|
||||||
semanticServices.getTrace().recordDeclarationResolution(psiClass, constructorDescriptor);
|
semanticServices.getTrace().recordDeclarationResolution(psiClass, constructorDescriptor);
|
||||||
}
|
}
|
||||||
@@ -128,12 +129,14 @@ public class JavaDescriptorResolver {
|
|||||||
Collections.<Annotation>emptyList(), // TODO
|
Collections.<Annotation>emptyList(), // TODO
|
||||||
false);
|
false);
|
||||||
constructorDescriptor.initialize(resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()));
|
constructorDescriptor.initialize(resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()));
|
||||||
|
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||||
classDescriptor.addConstructor(constructorDescriptor);
|
classDescriptor.addConstructor(constructorDescriptor);
|
||||||
semanticServices.getTrace().recordDeclarationResolution(constructor, constructorDescriptor);
|
semanticServices.getTrace().recordDeclarationResolution(constructor, constructorDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
semanticServices.getTrace().recordDeclarationResolution(psiClass, classDescriptor);
|
semanticServices.getTrace().recordDeclarationResolution(psiClass, classDescriptor);
|
||||||
|
|
||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.ErrorHandler;
|
import org.jetbrains.jet.lang.ErrorHandler;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||||
|
import org.jetbrains.jet.lang.resolve.JetScopeImpl;
|
||||||
import org.jetbrains.jet.lang.resolve.WritableScope;
|
import org.jetbrains.jet.lang.resolve.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
|
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
|
||||||
|
|
||||||
@@ -74,7 +75,18 @@ public class JetStandardClasses {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), JetScope.EMPTY);
|
private static final JetType ANY_TYPE = new JetTypeImpl(ANY.getTypeConstructor(), new JetScopeImpl() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public DeclarationDescriptor getContainingDeclaration() {
|
||||||
|
return STANDARD_CLASSES_NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Scope for Any";
|
||||||
|
}
|
||||||
|
});
|
||||||
private static final JetType NULLABLE_ANY_TYPE = TypeUtils.makeNullable(ANY_TYPE);
|
private static final JetType NULLABLE_ANY_TYPE = TypeUtils.makeNullable(ANY_TYPE);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO : attributes?
|
// TODO : attributes?
|
||||||
return new JetTypeImpl(Collections.<Annotation>emptyList(), constructor, nullable, newProjections, JetStandardClasses.STUB);
|
return new JetTypeImpl(Collections.<Annotation>emptyList(), constructor, nullable, newProjections, JetStandardClasses.STUB); // TODO : scope
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -640,6 +640,11 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
expression.accept(this);
|
expression.accept(this);
|
||||||
|
// Some recursive definitions (object expressions) must put their types in the cache manually:
|
||||||
|
if (trace.isProcessed(expression)) {
|
||||||
|
return trace.getBindingContext().getExpressionType(expression);
|
||||||
|
}
|
||||||
|
|
||||||
if (result instanceof DeferredType) {
|
if (result instanceof DeferredType) {
|
||||||
result = ((DeferredType) result).getActualType();
|
result = ((DeferredType) result).getActualType();
|
||||||
}
|
}
|
||||||
@@ -754,9 +759,14 @@ public class JetTypeInferrer {
|
|||||||
public void visitObjectLiteralExpression(final JetObjectLiteralExpression expression) {
|
public void visitObjectLiteralExpression(final JetObjectLiteralExpression expression) {
|
||||||
TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, new BindingTraceAdapter(trace) {
|
TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, new BindingTraceAdapter(trace) {
|
||||||
@Override
|
@Override
|
||||||
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) {
|
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull final DeclarationDescriptor descriptor) {
|
||||||
if (declaration == expression.getObjectDeclaration()) {
|
if (declaration == expression.getObjectDeclaration()) {
|
||||||
JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
|
JetType defaultType = new DeferredType(new LazyValue<JetType>() {
|
||||||
|
@Override
|
||||||
|
protected JetType compute() {
|
||||||
|
return ((ClassDescriptor) descriptor).getDefaultType();
|
||||||
|
}
|
||||||
|
});
|
||||||
result = defaultType;
|
result = defaultType;
|
||||||
if (!trace.isProcessed(expression)) {
|
if (!trace.isProcessed(expression)) {
|
||||||
recordExpressionType(expression, defaultType);
|
recordExpressionType(expression, defaultType);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.Annotation;
|
import org.jetbrains.jet.lang.descriptors.Annotation;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.ChainedScope;
|
||||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -70,13 +71,27 @@ public class TypeUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Annotation> noAnnotations = Collections.<Annotation>emptyList();
|
List<Annotation> noAnnotations = Collections.<Annotation>emptyList();
|
||||||
TypeConstructor constructor = new TypeConstructorImpl(null, noAnnotations, false, debugName.toString(), Collections.<TypeParameterDescriptor>emptyList(), types);
|
TypeConstructor constructor = new TypeConstructorImpl(
|
||||||
|
null,
|
||||||
|
noAnnotations,
|
||||||
|
false,
|
||||||
|
debugName.toString(),
|
||||||
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
|
types);
|
||||||
|
|
||||||
|
JetScope[] scopes = new JetScope[types.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (JetType type : types) {
|
||||||
|
scopes[i] = type.getMemberScope();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
return new JetTypeImpl(
|
return new JetTypeImpl(
|
||||||
noAnnotations,
|
noAnnotations,
|
||||||
constructor,
|
constructor,
|
||||||
nullable,
|
nullable,
|
||||||
Collections.<TypeProjection>emptyList(),
|
Collections.<TypeProjection>emptyList(),
|
||||||
JetStandardClasses.STUB);
|
new ChainedScope(null, scopes)); // TODO : check intersectibility, don't use a chanied scope
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) {
|
private static boolean canHaveSubtypes(JetTypeChecker typeChecker, JetType type) {
|
||||||
@@ -176,7 +191,7 @@ public class TypeUtils {
|
|||||||
private static List<TypeProjection> getArguments(@NotNull ClassDescriptor classDescriptor) {
|
private static List<TypeProjection> getArguments(@NotNull ClassDescriptor classDescriptor) {
|
||||||
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
List<TypeProjection> result = new ArrayList<TypeProjection>();
|
||||||
for (TypeParameterDescriptor parameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) {
|
for (TypeParameterDescriptor parameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) {
|
||||||
result.add(new TypeProjection(new JetTypeImpl(parameterDescriptor.getTypeConstructor(), JetScope.EMPTY))); // TODO : scope?
|
result.add(new TypeProjection(parameterDescriptor.getDefaultType()));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ public class DescriptorRenderer {
|
|||||||
renderName(descriptor, builder);
|
renderName(descriptor, builder);
|
||||||
if (!descriptor.getUpperBounds().isEmpty()) {
|
if (!descriptor.getUpperBounds().isEmpty()) {
|
||||||
JetType bound = descriptor.getUpperBounds().iterator().next();
|
JetType bound = descriptor.getUpperBounds().iterator().next();
|
||||||
if (bound != JetStandardClasses.getAnyType()) {
|
if (bound != JetStandardClasses.getDefaultBound()) {
|
||||||
builder.append(" : ").append(renderType(bound));
|
builder.append(" : ").append(renderType(bound));
|
||||||
if (descriptor.getUpperBounds().size() > 1) {
|
if (descriptor.getUpperBounds().size() > 1) {
|
||||||
builder.append(" (...)");
|
builder.append(" (...)");
|
||||||
|
|||||||
@@ -14,10 +14,8 @@ JetFile: TypeConstraints.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
TYPE_CONSTRAINT_LIST
|
TYPE_CONSTRAINT_LIST
|
||||||
TYPE_CONSTRAINT
|
TYPE_CONSTRAINT
|
||||||
TYPE_REFERENCE
|
REFERENCE_EXPRESSION
|
||||||
USER_TYPE
|
PsiElement(IDENTIFIER)('T')
|
||||||
REFERENCE_EXPRESSION
|
|
||||||
PsiElement(IDENTIFIER)('T')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -32,10 +30,8 @@ JetFile: TypeConstraints.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
TYPE_REFERENCE
|
REFERENCE_EXPRESSION
|
||||||
USER_TYPE
|
PsiElement(IDENTIFIER)('T')
|
||||||
REFERENCE_EXPRESSION
|
|
||||||
PsiElement(IDENTIFIER)('T')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
@@ -213,10 +213,8 @@ JetFile: PolymorphicClassObjects.jet
|
|||||||
PsiWhiteSpace('\n ')
|
PsiWhiteSpace('\n ')
|
||||||
TYPE_CONSTRAINT_LIST
|
TYPE_CONSTRAINT_LIST
|
||||||
TYPE_CONSTRAINT
|
TYPE_CONSTRAINT
|
||||||
TYPE_REFERENCE
|
REFERENCE_EXPRESSION
|
||||||
USER_TYPE
|
PsiElement(IDENTIFIER)('T')
|
||||||
REFERENCE_EXPRESSION
|
|
||||||
PsiElement(IDENTIFIER)('T')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
@@ -239,10 +237,8 @@ JetFile: PolymorphicClassObjects.jet
|
|||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(object)('object')
|
PsiElement(object)('object')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
TYPE_REFERENCE
|
REFERENCE_EXPRESSION
|
||||||
USER_TYPE
|
PsiElement(IDENTIFIER)('T')
|
||||||
REFERENCE_EXPRESSION
|
|
||||||
PsiElement(IDENTIFIER)('T')
|
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
PsiElement(COLON)(':')
|
PsiElement(COLON)(':')
|
||||||
PsiWhiteSpace(' ')
|
PsiWhiteSpace(' ')
|
||||||
|
|||||||
Reference in New Issue
Block a user