KT-691 Allow to create nested namespaces with dot delimiter

This commit is contained in:
Andrey Breslav
2011-11-30 15:06:55 +03:00
parent 7fd7bdb2b8
commit 49c29dd323
114 changed files with 496 additions and 209 deletions
@@ -142,5 +142,5 @@ public interface JetNodeTypes {
JetNodeType WHEN_CONDITION_IN_RANGE = new JetNodeType("WHEN_CONDITION_IN_RANGE", JetWhenConditionInRange.class);
JetNodeType WHEN_CONDITION_IS_PATTERN = new JetNodeType("WHEN_CONDITION_IS_PATTERN", JetWhenConditionIsPattern.class);
JetNodeType NAMESPACE_NAME = new JetNodeType("NAMESPACE_NAME", JetContainerNode.class);
JetNodeType NAMESPACE_HEADER = new JetNodeType("NAMESPACE_HEADER", JetNamespaceHeader.class);
}
@@ -115,17 +115,18 @@ public class JetParsing extends AbstractJetParsing {
* : modifiers "namespace" SimpleName{"."} SEMI?
* ;
*/
PsiBuilder.Marker namespaceHeader = mark();
PsiBuilder.Marker firstEntry = mark();
parseModifierList(MODIFIER_LIST, true);
if (at(NAMESPACE_KEYWORD)) {
advance(); // NAMESPACE_KEYWORD
parseNamespaceName();
if (at(LBRACE)) {
// Because it's blocked namespace and it will be parsed as one of top level objects
firstEntry.rollbackTo();
namespaceHeader.done(NAMESPACE_HEADER);
return;
}
@@ -135,6 +136,7 @@ public class JetParsing extends AbstractJetParsing {
} else {
firstEntry.rollbackTo();
}
namespaceHeader.done(NAMESPACE_HEADER);
// TODO: Duplicate with parsing imports in parseToplevelDeclarations
while (at(IMPORT_KEYWORD)) {
@@ -145,12 +147,18 @@ public class JetParsing extends AbstractJetParsing {
/* SimpleName{"."} */
private void parseNamespaceName() {
PsiBuilder.Marker nsName = mark();
expect(IDENTIFIER, "Expecting qualified name", NAMESPACE_NAME_RECOVERY_SET);
while (!eol() && at(DOT)) {
advance(); // DOT
while (true) {
expect(IDENTIFIER, "Namespace name must be a '.'-separated identifier list", NAMESPACE_NAME_RECOVERY_SET);
if (at(DOT)) {
nsName.done(REFERENCE_EXPRESSION);
advance(); // DOT
nsName = mark();
}
else {
nsName.drop();
break;
}
}
nsName.done(NAMESPACE_NAME);
}
/*
@@ -378,6 +386,7 @@ public class JetParsing extends AbstractJetParsing {
*/
private JetNodeType parseNamespaceBlock() {
assert _at(NAMESPACE_KEYWORD);
PsiBuilder.Marker namespaceHeader = mark();
advance(); // NAMESPACE_KEYWORD
if (at(LBRACE)) {
@@ -386,6 +395,7 @@ public class JetParsing extends AbstractJetParsing {
else {
parseNamespaceName();
}
namespaceHeader.done(NAMESPACE_HEADER);
if (!at(LBRACE)) {
error("A namespace block in '{...}' expected");
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.ArrayList;
@@ -26,6 +27,7 @@ public class JetAnnotatedExpression extends JetExpression {
return visitor.visitAnnotatedExpression(this, data);
}
@Nullable
public JetExpression getBaseExpression() {
return findChildByClass(JetExpression.class);
}
@@ -39,18 +39,23 @@ public class JetNamespace extends JetNamedDeclaration {
}
public String getName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier != null ? nameIdentifier.getText() : "";
String name = super.getName();
return name == null ? "" : name;
}
@NotNull
public JetNamespaceHeader getHeader() {
return (JetNamespaceHeader) findChildByType(JetNodeTypes.NAMESPACE_HEADER);
}
@Override
public PsiElement getNameIdentifier() {
return findChildByType(JetNodeTypes.NAMESPACE_NAME);
return getHeader().getNameIdentifier();
}
@Override
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
throw new UnsupportedOperationException(); // TODO
throw new UnsupportedOperationException();
}
}
@@ -0,0 +1,35 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List;
/**
* @author abreslav
*/
public class JetNamespaceHeader extends JetElement {
public JetNamespaceHeader(@NotNull ASTNode node) {
super(node);
}
@NotNull
public List<JetSimpleNameExpression> getParentNamespaceNames() {
return findChildrenByType(JetNodeTypes.REFERENCE_EXPRESSION);
}
@Nullable
public PsiElement getNameIdentifier() {
return findChildByType(JetTokens.IDENTIFIER);
}
@Override
public String getName() {
PsiElement nameIdentifier = getNameIdentifier();
return nameIdentifier == null ? "" : nameIdentifier.getText();
}
}
@@ -69,19 +69,7 @@ public class TypeHierarchyResolver {
declaration.accept(new JetVisitorVoid() {
@Override
public void visitNamespace(JetNamespace namespace) {
String name = JetPsiUtil.safeName(namespace.getName());
NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptorImpl(
owner.getOriginal(),
Collections.<AnnotationDescriptor>emptyList(), // TODO: annotations
name
);
namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope"));
owner.addNamespace(namespaceDescriptor);
context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor);
}
NamespaceDescriptorImpl namespaceDescriptor = createNamespaceDescriptorPathIfNeeded(namespace, owner);
context.getNamespaceDescriptors().put(namespace, namespaceDescriptor);
WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace()));
@@ -202,6 +190,35 @@ public class TypeHierarchyResolver {
}
}
private NamespaceDescriptorImpl createNamespaceDescriptorPathIfNeeded(JetNamespace namespace, NamespaceLike owner) {
NamespaceLike currentOwner = owner;
for (JetSimpleNameExpression nameExpression : namespace.getHeader().getParentNamespaceNames()) {
currentOwner = createNamespaceDescriptorIfNeeded(null, currentOwner, JetPsiUtil.safeName(nameExpression.getReferencedName()));
context.getTrace().record(REFERENCE_TARGET, nameExpression, currentOwner);
}
String name = JetPsiUtil.safeName(namespace.getName());
return createNamespaceDescriptorIfNeeded(namespace, currentOwner, name);
}
@NotNull
private NamespaceDescriptorImpl createNamespaceDescriptorIfNeeded(@Nullable JetNamespace namespace, @NotNull NamespaceLike owner, @NotNull String name) {
NamespaceDescriptorImpl namespaceDescriptor = owner.getNamespace(name);
if (namespaceDescriptor == null) {
namespaceDescriptor = new NamespaceDescriptorImpl(
owner.getOriginal(),
Collections.<AnnotationDescriptor>emptyList(), // TODO: annotations
name
);
namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope"));
owner.addNamespace(namespaceDescriptor);
if (namespace != null) {
context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor);
}
}
return namespaceDescriptor;
}
@NotNull
private ClassKind getClassKind(@NotNull JetClass jetClass) {
if (jetClass.isTrait()) return ClassKind.TRAIT;