diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java index 38186556f36..47e15fe4c71 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java @@ -39,7 +39,7 @@ import java.util.List; * @author max */ public class JetClass extends JetTypeParameterListOwner - implements JetClassOrObject, JetModifierListOwner, StubBasedPsiElement> { + implements JetClassOrObject, JetModifierListOwner, StubBasedPsiElement { private PsiJetClassStub stub; @@ -158,7 +158,7 @@ public class JetClass extends JetTypeParameterListOwner } @Override - public PsiJetClassStub getStub() { + public PsiJetClassStub getStub() { // TODO (stubs) return null; } @@ -198,4 +198,48 @@ public class JetClass extends JetTypeParameterListOwner Collections.reverse(parts); return StringUtil.join(parts, "."); } + + /** + * Returns the list of unqualified names that are indexed as the superclass names of this class. For the names that might be imported + * via an aliased import, includes both the original and the aliased name (reference resolution during inheritor search will sort this out). + * + * @return the list of possible superclass names + */ + @NotNull + public List getSuperNames() { + final JetDelegationSpecifierList delegationSpecifierList = getDelegationSpecifierList(); + if (delegationSpecifierList == null) return Collections.emptyList(); + final List specifiers = delegationSpecifierList.getDelegationSpecifiers(); + if (specifiers.size() == 0) return Collections.emptyList(); + List result = new ArrayList(); + for (JetDelegationSpecifier specifier : specifiers) { + final JetTypeReference typeReference = specifier.getTypeReference(); + if (typeReference != null) { + final JetTypeElement typeElement = typeReference.getTypeElement(); + if (typeElement instanceof JetUserType) { + final String referencedName = ((JetUserType) typeElement).getReferencedName(); + if (referencedName != null) { + addSuperName(result, referencedName); + } + } + } + } + return result; + } + + private void addSuperName(List result, String referencedName) { + result.add(referencedName); + if (getContainingFile() instanceof JetFile) { + final JetImportDirective directive = ((JetFile) getContainingFile()).findImportByAlias(referencedName); + if (directive != null) { + JetExpression reference = directive.getImportedReference(); + while (reference instanceof JetDotQualifiedExpression) { + reference = ((JetDotQualifiedExpression) reference).getSelectorExpression(); + } + if (reference instanceof JetSimpleNameExpression) { + result.add(((JetSimpleNameExpression) reference).getReferencedName()); + } + } + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java index c210ee0e273..c6daf28781c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java @@ -61,6 +61,16 @@ public class JetFile extends PsiFileBase implements JetDeclarationContainer { return PsiTreeUtil.getChildrenOfTypeAsList(this, JetImportDirective.class); } + @Nullable + public JetImportDirective findImportByAlias(@NotNull String name) { + for (JetImportDirective directive : getImportDirectives()) { + if (name.equals(directive.getAliasName())) { + return directive; + } + } + return null; + } + // scripts has no namespace header @Nullable public JetNamespaceHeader getNamespaceHeader() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java index e33c0798e97..ded2867ec72 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetClassStub.java @@ -18,13 +18,16 @@ package org.jetbrains.jet.lang.psi.stubs; import com.intellij.psi.stubs.StubElement; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetClass; +import java.util.List; + /** * @author Nikolay Krasko */ -public interface PsiJetClassStub extends StubElement { +public interface PsiJetClassStub extends StubElement { @NonNls @Nullable String getQualifiedName(); @@ -32,6 +35,9 @@ public interface PsiJetClassStub extends StubElement { @Nullable String getName(); + @NotNull + List getSuperNames(); + boolean isDeprecated(); boolean hasDeprecatedAnnotation(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java index b934561b9ca..5193cd98b27 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetClassElementType.java @@ -62,7 +62,8 @@ public class JetClassElementType extends JetStubElementType { - public static final int STUB_VERSION = 3; + public static final int STUB_VERSION = 4; public JetFileElementType() { super("jet.FILE", JetLanguage.INSTANCE); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java index 366bc0754bd..34de79d8d1b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetClassStubImpl.java @@ -19,37 +19,53 @@ package org.jetbrains.jet.lang.psi.stubs.impl; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; import com.intellij.util.io.StringRef; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; import org.jetbrains.jet.lang.psi.stubs.elements.JetClassElementType; +import java.util.ArrayList; +import java.util.List; + /** * @author Nikolay Krasko */ -public class PsiJetClassStubImpl extends StubBase implements PsiJetClassStub { +public class PsiJetClassStubImpl extends StubBase implements PsiJetClassStub { private final StringRef qualifiedName; private final StringRef name; + private final StringRef[] superNames; public PsiJetClassStubImpl( JetClassElementType type, final StubElement parent, @Nullable final String qualifiedName, - final String name) { + final String name, + final List superNames) { - this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name)); + this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name), wrapStrings(superNames)); + } + + private static StringRef[] wrapStrings(List names) { + StringRef[] refs = new StringRef[names.size()]; + for (int i = 0; i < names.size(); i++) { + refs[i] = StringRef.fromString(names.get(i)); + } + return refs; } public PsiJetClassStubImpl( JetClassElementType type, final StubElement parent, final StringRef qualifiedName, - final StringRef name) { + final StringRef name, + final StringRef[] superNames) { super(parent, type); this.qualifiedName = qualifiedName; this.name = name; + this.superNames = superNames; } @Override @@ -71,4 +87,14 @@ public class PsiJetClassStubImpl extends StubBase implements PsiJetCla public String getName() { return StringRef.toString(name); } + + @NotNull + @Override + public List getSuperNames() { + List result = new ArrayList(); + for (StringRef ref : superNames) { + result.add(ref.toString()); + } + return result; + } } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index b8ac9d358f8..88cfc9f789a 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -175,6 +175,7 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java index 90e94f197f7..5f8001f2fd4 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.psi.JetNamedFunction; */ public interface JetIndexKeys { StubIndexKey SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.class.shortName"); + StubIndexKey SUPERCLASS_NAME_KEY = StubIndexKey.createIndexKey("jet.class.superClassName"); StubIndexKey FQN_KEY = StubIndexKey.createIndexKey("jet.fqn"); StubIndexKey TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetSuperClassIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetSuperClassIndex.java new file mode 100644 index 00000000000..9be624138d1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetSuperClassIndex.java @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.stubs.StringStubIndexExtension; +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClassOrObject; + +import java.util.Collection; + +/** + * @author yole + */ +public class JetSuperClassIndex extends StringStubIndexExtension { + private static final JetSuperClassIndex ourInstance = new JetSuperClassIndex(); + public static JetSuperClassIndex getInstance() { + return ourInstance; + } + + @NotNull + @Override + public StubIndexKey getKey() { + return JetIndexKeys.SUPERCLASS_NAME_KEY; + } + + @Override + public Collection get(final String s, final Project project, @NotNull final GlobalSearchScope scope) { + return super.get(s, project, new JetSourceFilterScope(scope)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java b/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java index 3b496cfdf4d..be72f9a0108 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java @@ -37,6 +37,10 @@ public class StubIndexServiceImpl implements StubIndexService { if (fqn != null) { sink.occurrence(JetIndexKeys.FQN_KEY, fqn); } + + for (String superName : stub.getSuperNames()) { + sink.occurrence(JetIndexKeys.SUPERCLASS_NAME_KEY, superName); + } } @Override diff --git a/idea/tests/org/jetbrains/jet/plugin/stubs/JetStubsTest.java b/idea/tests/org/jetbrains/jet/plugin/stubs/JetStubsTest.java new file mode 100644 index 00000000000..973e87e16bd --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/stubs/JetStubsTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.stubs; + +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetDeclaration; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; +import org.jetbrains.jet.plugin.JetLightProjectDescriptor; + +import java.util.List; + +/** + * @author yole + */ +public class JetStubsTest extends LightCodeInsightFixtureTestCase { + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JetLightProjectDescriptor.INSTANCE; + } + + public void testSuperclassNames() { + final PsiFile psiFile = myFixture.configureByText("foo.kt", "import java.util.ArrayList as alist\nclass C(): alist() { }"); + final List declarations = ((JetFile) psiFile).getDeclarations(); + final JetClass jetClass = (JetClass) declarations.get(0); + final PsiJetClassStub stub = JetStubElementTypes.CLASS.createStub(jetClass, null); + final List names = stub.getSuperNames(); + assertSameElements(names, "ArrayList", "alist"); + } +}