Namespace types are only allowed in appropriate contexts
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class JetModuleUtil {
|
public class JetModuleUtil {
|
||||||
public static JetScope getRootNamespaceScope(JetElement expression) {
|
public static NamespaceType getRootNamespaceType(JetElement expression) {
|
||||||
// TODO: this is a stub: at least the modules' root namespaces must be indexed here
|
// TODO: this is a stub: at least the modules' root namespaces must be indexed here
|
||||||
return JetScope.EMPTY;
|
return new NamespaceType("<namespace_root>", JetScope.EMPTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public class TopDownAnalyzer {
|
|||||||
if (importDirective.isAllUnder()) {
|
if (importDirective.isAllUnder()) {
|
||||||
JetExpression importedReference = importDirective.getImportedReference();
|
JetExpression importedReference = importDirective.getImportedReference();
|
||||||
if (importedReference != null) {
|
if (importedReference != null) {
|
||||||
JetType type = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).getType(namespaceScope, importedReference, false);
|
JetType type = semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).getTypeWithNamespaces(namespaceScope, importedReference, false);
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
namespaceScope.importScope(type.getMemberScope());
|
namespaceScope.importScope(type.getMemberScope());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,9 +202,9 @@ public class TypeResolver {
|
|||||||
if (referencedName == null) {
|
if (referencedName == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ClassifierDescriptor classifierDescriptor = null;
|
ClassifierDescriptor classifierDescriptor;
|
||||||
if (userType.isAbsoluteInRootNamespace()) {
|
if (userType.isAbsoluteInRootNamespace()) {
|
||||||
classifierDescriptor = JetModuleUtil.getRootNamespaceScope(userType).getClassifier(referencedName);
|
classifierDescriptor = JetModuleUtil.getRootNamespaceType(userType).getMemberScope().getClassifier(referencedName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetUserType qualifier = userType.getQualifier();
|
JetUserType qualifier = userType.getQualifier();
|
||||||
@@ -238,7 +238,7 @@ public class TypeResolver {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private NamespaceDescriptor resolveNamespace(JetScope scope, JetUserType userType) {
|
private NamespaceDescriptor resolveNamespace(JetScope scope, JetUserType userType) {
|
||||||
if (userType.isAbsoluteInRootNamespace()) {
|
if (userType.isAbsoluteInRootNamespace()) {
|
||||||
return resolveNamespace(JetModuleUtil.getRootNamespaceScope(userType), userType);
|
return resolveNamespace(JetModuleUtil.getRootNamespaceType(userType).getMemberScope(), userType);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetUserType qualifier = userType.getQualifier();
|
JetUserType qualifier = userType.getQualifier();
|
||||||
|
|||||||
@@ -150,7 +150,8 @@ public class ErrorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isErrorType(JetType type) {
|
public static boolean isErrorType(JetType type) {
|
||||||
return type instanceof ErrorTypeImpl || isError(type.getConstructor());
|
return type instanceof ErrorTypeImpl ||
|
||||||
|
isError(type.getConstructor());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ErrorTypeImpl implements JetType {
|
private static class ErrorTypeImpl implements JetType {
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ public class JetTypeInferrer {
|
|||||||
return new TypeInferrerVisitor(scope, preferBlock).getType(expression);
|
return new TypeInferrerVisitor(scope, preferBlock).getType(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, final boolean preferBlock) {
|
||||||
|
return new TypeInferrerVisitorWithNamespaces(scope, preferBlock).getType(expression);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<JetType> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
|
private List<JetType> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
|
||||||
List<JetType> argumentTypes = new ArrayList<JetType>();
|
List<JetType> argumentTypes = new ArrayList<JetType>();
|
||||||
@@ -557,7 +561,7 @@ public class JetTypeInferrer {
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private class TypeInferrerVisitor extends JetVisitor {
|
private class TypeInferrerVisitor extends JetVisitor {
|
||||||
private final JetScope scope;
|
protected final JetScope scope;
|
||||||
private final boolean preferBlock;
|
private final boolean preferBlock;
|
||||||
|
|
||||||
protected JetType result;
|
protected JetType result;
|
||||||
@@ -574,13 +578,18 @@ public class JetTypeInferrer {
|
|||||||
visitor = this;
|
visitor = this;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
visitor = new TypeInferrerVisitor(scope, preferBlock);
|
visitor = createNew(scope, preferBlock);
|
||||||
}
|
}
|
||||||
JetType type = visitor.getType(expression);
|
JetType type = visitor.getType(expression);
|
||||||
visitor.result = null;
|
visitor.result = null;
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock) {
|
||||||
|
return new TypeInferrerVisitor(scope, preferBlock);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public JetType getType(@NotNull JetExpression expression) {
|
public JetType getType(@NotNull JetExpression expression) {
|
||||||
assert result == null;
|
assert result == null;
|
||||||
@@ -640,19 +649,33 @@ public class JetTypeInferrer {
|
|||||||
semanticServices.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
|
semanticServices.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else if (furtherNameLookup(expression, referencedName)) {
|
||||||
NamespaceDescriptor namespace = scope.getNamespace(referencedName);
|
return;
|
||||||
if (namespace != null) {
|
|
||||||
trace.recordReferenceResolution(expression, namespace);
|
|
||||||
result = namespace.getNamespaceType();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
semanticServices.getErrorHandler().unresolvedReference(expression);
|
semanticServices.getErrorHandler().unresolvedReference(expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
|
||||||
|
NamespaceType namespaceType = lookupNamespaceType(expression, referencedName);
|
||||||
|
if (namespaceType != null) {
|
||||||
|
semanticServices.getErrorHandler().genericError(expression.getNode(), "Expression expected, but a namespace name found");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
|
||||||
|
NamespaceDescriptor namespace = scope.getNamespace(referencedName);
|
||||||
|
if (namespace == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
trace.recordReferenceResolution(expression, namespace);
|
||||||
|
return namespace.getNamespaceType();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
|
public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) {
|
||||||
if (preferBlock && !expression.hasParameterSpecification()) {
|
if (preferBlock && !expression.hasParameterSpecification()) {
|
||||||
@@ -1164,7 +1187,7 @@ public class JetTypeInferrer {
|
|||||||
// TODO : functions
|
// TODO : functions
|
||||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||||
JetExpression receiverExpression = expression.getReceiverExpression();
|
JetExpression receiverExpression = expression.getReceiverExpression();
|
||||||
JetType receiverType = getType(scope, receiverExpression, false);
|
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
checkNullSafety(receiverType, expression);
|
checkNullSafety(receiverType, expression);
|
||||||
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
|
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
|
||||||
@@ -1467,9 +1490,39 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitJetElement(JetElement elem) {
|
public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
|
||||||
semanticServices.getErrorHandler().genericError(elem.getNode(), "Unsupported element: " + elem + " " + elem.getClass().getCanonicalName());
|
semanticServices.getErrorHandler().genericError(expression.getNode(), "'namespace' is not an expression");
|
||||||
|
result = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJetElement(JetElement elem) {
|
||||||
|
semanticServices.getErrorHandler().genericError(elem.getNode(), "[JetTypeInferrer] Unsupported element: " + elem + " " + elem.getClass().getCanonicalName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor {
|
||||||
|
private TypeInferrerVisitorWithNamespaces(@NotNull JetScope scope, boolean preferBlock) {
|
||||||
|
super(scope, preferBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public TypeInferrerVisitor createNew(JetScope scope, boolean preferBlock) {
|
||||||
|
return new TypeInferrerVisitorWithNamespaces(scope, preferBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) {
|
||||||
|
result = JetModuleUtil.getRootNamespaceType(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) {
|
||||||
|
result = lookupNamespaceType(expression, referencedName);
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
|
private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace root
|
||||||
|
|
||||||
|
namespace a {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val x = <error>a</error>
|
||||||
|
val y2 = <error>namespace</error>
|
||||||
Reference in New Issue
Block a user