diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 73651fa98f2..cae0d722989 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -45,6 +45,23 @@ public class TypeResolver { if (referenceExpression == null || referencedName == null) { return; } + + if (type.getTypeArguments().isEmpty() && type.getQualifier() == null) { + TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(referencedName); + if (typeParameterDescriptor != null) { + trace.recordReferenceResolution(referenceExpression, typeParameterDescriptor); + result[0] = new JetTypeImpl( + attributes, + typeParameterDescriptor.getTypeConstructor(), + nullable || hasNullableBound(typeParameterDescriptor), + Collections.emptyList(), + // TODO : joint domain + JetStandardClasses.STUB + ); + return; + } + } + ClassDescriptor classDescriptor = resolveClass(scope, type); if (classDescriptor != null) { trace.recordReferenceResolution(referenceExpression, classDescriptor); @@ -62,25 +79,6 @@ public class TypeResolver { ); } } - else if (type.getTypeArguments().isEmpty()) { - TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(referencedName); - if (typeParameterDescriptor != null) { - trace.recordReferenceResolution(referenceExpression, typeParameterDescriptor); - result[0] = new JetTypeImpl( - attributes, - typeParameterDescriptor.getTypeConstructor(), - nullable || hasNullableBound(typeParameterDescriptor), - Collections.emptyList(), - // TODO : joint domain - JetStandardClasses.STUB - ); - } else { - semanticServices.getErrorHandler().unresolvedReference(referenceExpression); - } - } - else { - semanticServices.getErrorHandler().unresolvedReference(referenceExpression); - } } @Override @@ -173,7 +171,12 @@ public class TypeResolver { } @Nullable - public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) { + public ClassDescriptor resolveClassByUserType(JetScope scope, JetUserType userType) { + return resolveClass(scope, userType); + } + + @Nullable + private ClassDescriptor resolveClass(JetScope scope, JetUserType userType) { JetSimpleNameExpression expression = userType.getReferenceExpression(); if (expression == null) { return null; @@ -182,16 +185,29 @@ public class TypeResolver { if (referencedName == null) { return null; } + ClassDescriptor classDescriptor = null; if (userType.isAbsoluteInRootNamespace()) { - return JetModuleUtil.getRootNamespaceScope(userType).getClass(referencedName); + classDescriptor = JetModuleUtil.getRootNamespaceScope(userType).getClass(referencedName); } - JetUserType qualifier = userType.getQualifier(); - if (qualifier != null) { - scope = resolveClassLookupScope(scope, qualifier); + else { + JetUserType qualifier = userType.getQualifier(); + if (qualifier != null) { + scope = resolveClassLookupScope(scope, qualifier); + } + if (scope == null) { + return null; + } + classDescriptor = scope.getClass(referencedName); } - return scope.getClass(referencedName); + + if (classDescriptor == null) { + semanticServices.getErrorHandler().unresolvedReference(expression); + } + + return classDescriptor; } + @Nullable private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType) { ClassDescriptor classDescriptor = resolveClass(scope, userType); if (classDescriptor != null) { @@ -200,7 +216,7 @@ public class TypeResolver { NamespaceDescriptor namespaceDescriptor = resolveNamespace(scope, userType); if (namespaceDescriptor == null) { - return JetScope.EMPTY; + return null; } return namespaceDescriptor.getMemberScope(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 98686b28777..2206254e1c9 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -92,12 +92,13 @@ public class JetTypeInferrer { return result; } - @NotNull - private JetExpression deparenthesize(@NotNull JetExpression expression) { - while (expression instanceof JetParenthesizedExpression) { - expression = ((JetParenthesizedExpression) expression).getExpression(); + @Nullable + private static JetExpression deparenthesize(@NotNull JetExpression expression) { + JetExpression result = expression; + while (result instanceof JetParenthesizedExpression) { + result = ((JetParenthesizedExpression) expression).getExpression(); } - return expression; + return result; } @Nullable @@ -158,9 +159,10 @@ public class JetTypeInferrer { JetExpression selectorExpression = expression.getSelectorExpression(); if (selectorExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression referenceExpression = (JetSimpleNameExpression) selectorExpression; + String referencedName = referenceExpression.getReferencedName(); - if (receiverType != null) { - result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName()); + if (receiverType != null && referencedName != null) { + result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName); reference[0] = referenceExpression; } } else { @@ -171,8 +173,11 @@ public class JetTypeInferrer { @Override public void visitSimpleNameExpression(JetSimpleNameExpression expression) { // a -- create a hierarchical lookup domain for this.a - result[0] = semanticServices.getOverloadResolver().getOverloadDomain(null, scope, expression.getReferencedName()); - reference[0] = expression; + String referencedName = expression.getReferencedName(); + if (referencedName != null) { + result[0] = semanticServices.getOverloadResolver().getOverloadDomain(null, scope, referencedName); + reference[0] = expression; + } } @Override @@ -498,22 +503,29 @@ public class JetTypeInferrer { @Override public void visitThisExpression(JetThisExpression expression) { - // TODO : qualified this, e.g. Foo.this + // TODO : qualified this, e.g. this@Foo JetType thisType = scope.getThisType(); JetTypeReference superTypeQualifier = expression.getSuperTypeQualifier(); if (superTypeQualifier != null) { - // This cast must be safe (assuming the PSI doesn't contain errors) - JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement(); - ClassDescriptor superclass = typeResolver.resolveClass(scope, typeElement); - Collection supertypes = thisType.getConstructor().getSupertypes(); - Map substitutionContext = TypeUtils.buildSubstitutionContext(thisType); - for (JetType declaredSupertype : supertypes) { - if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) { - result = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, declaredSupertype, Variance.INVARIANT); - break; + JetTypeElement superTypeElement = superTypeQualifier.getTypeElement(); + // Errors are reported by the parser + if (superTypeElement instanceof JetUserType) { + JetUserType typeElement = (JetUserType) superTypeElement; + ClassDescriptor superclass = typeResolver.resolveClassByUserType(scope, typeElement); + if (superclass != null) { + Collection supertypes = thisType.getConstructor().getSupertypes(); + Map substitutionContext = TypeUtils.buildSubstitutionContext(thisType); + for (JetType declaredSupertype : supertypes) { + if (declaredSupertype.getConstructor().equals(superclass.getTypeConstructor())) { + result = TypeSubstitutor.INSTANCE.safeSubstitute(substitutionContext, declaredSupertype, Variance.INVARIANT); + break; + } + } + if (result == null) { + semanticServices.getErrorHandler().genericError(superTypeElement.getNode(), "Not a superclass"); + } } } - assert result != null; } else { result = thisType; } @@ -541,7 +553,10 @@ public class JetTypeInferrer { if (finallyBlock == null) { for (JetCatchClause catchClause : catchClauses) { // TODO: change scope here - types.add(getType(scope, catchClause.getCatchBody(), true)); + JetExpression catchBody = catchClause.getCatchBody(); + if (catchBody != null) { + types.add(getType(scope, catchBody, true)); + } } } else { types.add(getType(scope, finallyBlock.getFinalExpression(), true)); @@ -650,6 +665,7 @@ public class JetTypeInferrer { propertyDescriptor = classDescriptorResolver.resolveValueParameterDescriptor(scope.getContainingDeclaration(), scope, loopParameter); JetType actualParameterType = propertyDescriptor.getOutType(); if (expectedParameterType != null && + actualParameterType != null && !semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) { semanticServices.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType); } @@ -860,7 +876,10 @@ public class JetTypeInferrer { List types = new ArrayList(); for (JetTypeProjection projection : typeArguments) { // TODO : check that there's no projection - types.add(typeResolver.resolveType(scope, projection.getTypeReference())); + JetTypeReference typeReference = projection.getTypeReference(); + if (typeReference != null) { + types.add(typeResolver.resolveType(scope, typeReference)); + } } List positionedValueArguments = new ArrayList(); @@ -889,7 +908,6 @@ public class JetTypeInferrer { @Override public void visitIsExpression(JetIsExpression expression) { // TODO : patterns and everything - System.out.println("Pattern matching is not supported yet."); result = semanticServices.getStandardLibrary().getBooleanType(); } diff --git a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java index 269577ed047..8e4c565f510 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetQuickDocumentationProvider.java @@ -47,7 +47,7 @@ public class JetQuickDocumentationProvider extends QuickDocumentationProvider { private String render(DeclarationDescriptor declarationDescriptor) { String text = DescriptorUtil.renderPresentableText(declarationDescriptor); -// text = text.replaceAll("<", "<"); + text = text.replaceAll("<", "<"); return text; }