From 2826db7d9adcde8274ab334fcd2811c3317c7665 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Tue, 31 Jan 2012 14:10:08 +0400 Subject: [PATCH] KT-1103 Public outer function from different package and source file is not visible in completion: - Stubs elements are enabled - Changed method for selecting indexing policy for plugin and compiler - Quick fix for import unresolved top-level function added --- .../resolve/java/JavaDescriptorResolver.java | 3 +- .../lang/resolve/java/JavaPackageScope.java | 3 - .../jet/lang/parsing/JetParserDefinition.java | 19 +- .../org/jetbrains/jet/lang/psi/JetFile.java | 17 ++ .../jet/lang/psi/JetNamedFunction.java | 29 ++- .../lang/psi/stubs/PsiJetFunctionStub.java | 14 +- .../stubs/elements/JetClassElementType.java | 12 +- .../elements/JetFakeStubElementFactory.java | 28 --- .../stubs/elements/JetFileElementType.java | 17 -- .../stubs/elements/JetFileStubBuilder.java | 2 +- .../elements/JetFunctionElementType.java | 38 +++- .../stubs/elements/JetStubElementFactory.java | 9 - .../stubs/elements/JetStubElementType.java | 9 +- .../stubs/elements/JetStubElementTypes.java | 6 +- .../psi/stubs/elements/StubIndexService.java | 27 +++ .../elements/StubIndexServiceFactory.java | 18 ++ .../stubs/impl/PsiJetFunctionStubImpl.java | 59 +++--- idea/src/META-INF/plugin.xml | 23 ++- .../jet/plugin/ParserConfigurator.java | 15 -- .../plugin/actions/JetAddImportAction.java | 2 +- .../jet/plugin/caches/JetShortNamesCache.java | 42 ++++ .../completion/DescriptorLookupConverter.java | 19 +- .../completion/JetCompletionContributor.java | 182 ++++++++++++++---- .../completion/LookupPositionObject.java | 43 +++++ ...lassFix.java => ImportClassAndFunFix.java} | 49 ++++- .../jet/plugin/quickfix/QuickFixes.java | 2 +- .../references/JetSimpleNameReference.java | 2 +- .../JetExtensionFunctionNameIndex.java | 21 ++ .../jet/plugin/stubindex/JetIndexKeys.java | 12 +- .../JetIndexedStubElementFactory.java | 40 ---- .../stubindex/JetShortFunctionNameIndex.java | 14 +- .../stubindex/StubIndexServiceImpl.java | 35 ++++ .../completion/basic/VariableClassName.kt | 2 + .../autoImports/afterFunctionImport.kt | 8 + .../beforeFunctionImport.Data.Sample.kt | 7 + .../autoImports/beforeFunctionImport.Main.kt | 6 + .../handlers/FunctionsHandlerTest.java | 5 +- 37 files changed, 569 insertions(+), 270 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFakeStubElementFactory.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementFactory.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexService.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexServiceFactory.java delete mode 100644 idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/LookupPositionObject.java rename idea/src/org/jetbrains/jet/plugin/quickfix/{ImportClassFix.java => ImportClassAndFunFix.java} (76%) create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetExtensionFunctionNameIndex.java delete mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java create mode 100644 idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java create mode 100644 idea/testData/quickfix/autoImports/afterFunctionImport.kt create mode 100644 idea/testData/quickfix/autoImports/beforeFunctionImport.Data.Sample.kt create mode 100644 idea/testData/quickfix/autoImports/beforeFunctionImport.Main.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 96e0b73079b..ba5b602a213 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -1110,7 +1110,8 @@ public class JavaDescriptorResolver { } @NotNull - public Set resolveFunctionGroup(@NotNull DeclarationDescriptor descriptor, @NotNull PsiClass psiClass, @NotNull String methodName, boolean staticMembers) { + public Set resolveFunctionGroup(@NotNull DeclarationDescriptor descriptor, @NotNull PsiClass psiClass, + @NotNull String methodName, boolean staticMembers) { ResolverScopeData resolverScopeData = getResolverScopeData(descriptor, new PsiClassWrapper(psiClass)); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 884c26ad16f..ebb7af8502e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -8,12 +8,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import java.util.Collection; -import java.util.Collections; -import java.util.Set; /** * @author abreslav diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java index 9ee73e0aeba..c7c898e1180 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParserDefinition.java @@ -16,27 +16,14 @@ import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetNodeType; -import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.stubs.elements.JetFakeStubElementFactory; -import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementFactory; import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementType; +import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lexer.JetLexer; import org.jetbrains.jet.lexer.JetTokens; public class JetParserDefinition implements ParserDefinition { - // TODO (stubs): - private static JetStubElementFactory stubElementFactory = new JetFakeStubElementFactory(); - - public static void setStubFactory(JetStubElementFactory factory) { - stubElementFactory = factory; - } - - public static JetStubElementFactory getStubElementTypeFactory() { - return stubElementFactory; - } - public JetParserDefinition() { if (!ApplicationManager.getApplication().isCommandLine()) { } @@ -52,9 +39,7 @@ public class JetParserDefinition implements ParserDefinition { } public IFileElementType getFileNodeType() { - // TODO (stubs) - return JetNodeTypes.JET_FILE; - // return JetStubElementTypes.FILE; + return JetStubElementTypes.FILE; } @NotNull 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 3b035ca8607..5aa1d427b15 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFile.java @@ -7,6 +7,8 @@ import com.intellij.extapi.psi.PsiFileBase; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.stubs.StubElement; +import com.intellij.psi.stubs.StubTree; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetNodeTypes; @@ -58,4 +60,19 @@ public class JetFile extends PsiFileBase { visitor.visitFile(this); } } + + @Override + public StubElement getStub() { + return super.getStub(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public StubTree calcStubTree() { + return super.calcStubTree(); //To change body of overridden methods use File | Settings | File Templates. + } + + @Override + public StubTree getStubTree() { + return super.getStubTree(); //To change body of overridden methods use File | Settings | File Templates. + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java index 3786dfe3fc6..913beb09de4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java @@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.stubs.IStubElementType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lexer.JetTokens; @@ -66,11 +67,37 @@ public class JetNamedFunction extends JetFunction implements StubBasedPsiElement return this; } + /** + * Returns full qualified name for function "package_fqn.function_name" + * Not null for top level functions. + * @return + */ + @Nullable + public String getQualifiedName() { + final PsiJetFunctionStub stub = getStub(); + if (stub != null) { + // TODO (stubs): return stub.getQualifiedName(); + } + + PsiElement parent = getParent(); + if (parent instanceof JetFile) { + JetFile jetFile = (JetFile) parent; + final String fileFQN = JetPsiUtil.getFQName(jetFile); + if (!fileFQN.isEmpty()) { + return fileFQN + "." + getName(); + } + + return getName(); + } + + return null; + } + @Override public IStubElementType getElementType() { return JetStubElementTypes.FUNCTION; } - + @Override public PsiJetFunctionStub getStub() { // TODO (stubs) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java index 3d8af9463a4..efe3902ed1c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/PsiJetFunctionStub.java @@ -12,11 +12,17 @@ public interface PsiJetFunctionStub extends StubElement< @Nullable String getName(); - boolean isDeclaration(); + /** + * Is function defined in directly in package. + * @return + */ + boolean isTopLevel(); + + /** + * Does function extends some type. + */ + boolean isExtension(); @NotNull String[] getAnnotations(); - - @NotNull - String getReturnTypeText(); } 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 8ed623b10a9..f6c94df4fa2 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 @@ -13,17 +13,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetClassStubImpl; -import org.jetbrains.jet.plugin.JetLanguage; import java.io.IOException; /** * @author Nikolay Krasko */ -public abstract class JetClassElementType extends JetStubElementType { +public class JetClassElementType extends JetStubElementType { public JetClassElementType(@NotNull @NonNls String debugName) { - super(debugName, JetLanguage.INSTANCE); + super(debugName); } @Override @@ -33,7 +32,6 @@ public abstract class JetClassElementType extends JetStubElementType { return STUB_VERSION; } - @Override - public boolean shouldBuildStubFor(final VirtualFile file) { - // TODO: - return true; - -// final VirtualFile dir = file.getParent(); -// return dir == null || dir.getUserData(LanguageLevel.KEY) != null; - } - - @Override - public ASTNode createNode(final CharSequence text) { - // TODO (stub): - return super.createNode(text); - } - @Override public String getExternalId() { return "jet.FILE"; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java index 2b93cb40860..1c9bb78bcf7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFileStubBuilder.java @@ -17,7 +17,7 @@ public class JetFileStubBuilder extends DefaultStubBuilder { if (!(file instanceof JetFile)) return super.createStubForFile(file); JetFile jetFile = (JetFile) file; - + // TODO (stubs): String packageName = "default"; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java index 12f2eda3c83..0a48dfd030b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetFunctionElementType.java @@ -3,29 +3,31 @@ package org.jetbrains.jet.lang.psi.stubs.elements; import com.intellij.lang.ASTNode; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; +import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; +import com.intellij.util.io.StringRef; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub; import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; -import org.jetbrains.jet.plugin.JetLanguage; +import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetFunctionStubImpl; import java.io.IOException; /** * @author Nikolay Krasko */ -public abstract class JetFunctionElementType extends JetStubElementType { +public class JetFunctionElementType extends JetStubElementType { public JetFunctionElementType(@NotNull @NonNls String debugName) { - super(debugName, JetLanguage.INSTANCE); + super(debugName); } @Override - public JetFunction createPsiFromAst(@NotNull ASTNode node) { + public JetNamedFunction createPsiFromAst(@NotNull ASTNode node) { return new JetNamedFunction(node); } @@ -35,22 +37,38 @@ public abstract class JetFunctionElementType extends JetStubElementType extends ILightStubElementType { - public JetStubElementType(@NotNull @NonNls String debugName, @Nullable Language language) { - super(debugName, language); + public JetStubElementType(@NotNull @NonNls String debugName) { + super(debugName, JetLanguage.INSTANCE); } - - public abstract PsiT createPsiFromAst(@NotNull ASTNode node); protected StubPsiFactory getPsiFactory(StubT stub) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java index e37bf075100..5259b300b1d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/JetStubElementTypes.java @@ -1,13 +1,11 @@ package org.jetbrains.jet.lang.psi.stubs.elements; -import org.jetbrains.jet.lang.parsing.JetParserDefinition; - /** * @author Nikolay Krasko */ public interface JetStubElementTypes { JetFileElementType FILE = new JetFileElementType(); - JetClassElementType CLASS = JetParserDefinition.getStubElementTypeFactory().getClassElementType(); - JetFunctionElementType FUNCTION = JetParserDefinition.getStubElementTypeFactory().getFunctionElementType(); + JetClassElementType CLASS = new JetClassElementType("CLASS"); + JetFunctionElementType FUNCTION = new JetFunctionElementType("FUN"); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexService.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexService.java new file mode 100644 index 00000000000..e470750d4e0 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexService.java @@ -0,0 +1,27 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.psi.stubs.IndexSink; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; + +/** + * @author Nikolay Krasko + */ +public interface StubIndexService { + + /** + * Default implementation with no indexing. + */ + StubIndexService NO_INDEX_SERVICE = new StubIndexService() { + @Override + public void indexClass(PsiJetClassStub stub, IndexSink sink) { + } + + @Override + public void indexFunction(PsiJetFunctionStub stub, IndexSink sink) { + } + }; + + void indexClass(PsiJetClassStub stub, IndexSink sink); + void indexFunction(PsiJetFunctionStub stub, IndexSink sink); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexServiceFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexServiceFactory.java new file mode 100644 index 00000000000..d1db243e3cf --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/elements/StubIndexServiceFactory.java @@ -0,0 +1,18 @@ +package org.jetbrains.jet.lang.psi.stubs.elements; + +import com.intellij.openapi.components.ServiceManager; + +/** + * @author Nikolay Krasko + */ +final class StubIndexServiceFactory { + + private StubIndexServiceFactory() { + } + + public static StubIndexService getInstance() { + // If executed in plugin service will be registered + final StubIndexService registeredService = ServiceManager.getService(StubIndexService.class); + return registeredService != null ? registeredService : StubIndexService.NO_INDEX_SERVICE; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java index b8f580be58e..cc44d2f851d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/stubs/impl/PsiJetFunctionStubImpl.java @@ -3,7 +3,9 @@ package org.jetbrains.jet.lang.psi.stubs.impl; import com.intellij.psi.stubs.IStubElementType; 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.JetFunction; import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; @@ -11,49 +13,44 @@ import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; * @author Nikolay Krasko */ public class PsiJetFunctionStubImpl extends StubBase implements PsiJetFunctionStub { - protected PsiJetFunctionStubImpl(StubElement parent, IStubElementType elementType) { - super(parent, elementType); + + private final StringRef nameRef; + private final boolean isTopLevel; + private final boolean isExtension; + + public PsiJetFunctionStubImpl(@NotNull IStubElementType elementType, @NotNull StubElement parent, + @Nullable String name, boolean isTopLevel, boolean isExtension) { + this(elementType, parent, StringRef.fromString(name), isTopLevel, isExtension); } -// public PsiJetFunctionStubImpl( -// Jet type, -// final StubElement parent, -// final String qualifiedName, -// final String name) { -// -// this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name)); -// } -// -// public PsiJetFunctionStubImpl( -// JetClassElementType type, -// final StubElement parent, -// final StringRef qualifiedName, -// final StringRef name) { -// -// super(parent, type); -// this.qualifiedName = qualifiedName; -// this.name = name; -// } + public PsiJetFunctionStubImpl(@NotNull IStubElementType elementType, @NotNull StubElement parent, + @Nullable StringRef nameRef, boolean isTopLevel, boolean isExtension) { + super(parent, elementType); + + this.nameRef = nameRef; + this.isTopLevel = isTopLevel; + this.isExtension = isExtension; + } @Override public String getName() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return StringRef.toString(nameRef); } @Override - public boolean isDeclaration() { - return false; //To change body of implemented methods use File | Settings | File Templates. + public boolean isTopLevel() { + return isTopLevel; + } + + @Override + public boolean isExtension() { + return isExtension; } @NotNull @Override public String[] getAnnotations() { - return new String[0]; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - public String getReturnTypeText() { - return null; //To change body of implemented methods use File | Settings | File Templates. + // TODO (stubs) + return new String[0]; } } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 5403612d695..476da74b585 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -4,9 +4,6 @@ @snapshot@ JetBrains - - - org.jetbrains.jet.plugin.compiler.JetCompilerManager @@ -44,6 +41,9 @@ + + @@ -57,13 +57,18 @@ - + + + + - - + + @@ -91,6 +96,12 @@ + + + + + + diff --git a/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java b/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java deleted file mode 100644 index 36eb6db31d4..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/ParserConfigurator.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.jetbrains.jet.plugin; - -/** - * Configures jet parser for using indexed stubs instead of default set. - * So if parser is used from IDEA it creates indexed stubs, if not direct psi elements are used. - * - * IMPORTANT: Should be called before loading parser. - * - * @author Nikolay Krasko - */ -public class ParserConfigurator { -// static { -// JetParserDefinition.setStubFactory(new JetIndexedStubElementFactory()); -// } -} diff --git a/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java b/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java index 21722dc2176..4a7d3fd9a72 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/JetAddImportAction.java @@ -129,7 +129,7 @@ public class JetAddImportAction implements QuestionAction { }; } - protected void addImport(final PsiElement element, final Project project, final String selectedImport) { + protected static void addImport(final PsiElement element, final Project project, final String selectedImport) { PsiDocumentManager.getInstance(project).commitAllDocuments(); CommandProcessor.getInstance().executeCommand(project, new Runnable() { diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java index 86baba1ba8e..a206a38e32d 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetShortNamesCache.java @@ -16,8 +16,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; +import org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex; +import org.jetbrains.jet.plugin.stubindex.JetShortFunctionNameIndex; import java.util.ArrayList; import java.util.Collection; @@ -107,6 +110,45 @@ public class JetShortNamesCache extends PsiShortNamesCache { } }); } + + public Collection getAllExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) { + return JetExtensionFunctionNameIndex.getInstance().get(name, project, scope); + } + + @NotNull + public Collection getAllTopLevelFunctionNames() { + return JetShortFunctionNameIndex.getInstance().getAllKeys(project); + } + + public Collection getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) { + return JetShortFunctionNameIndex.getInstance().get(name, project, scope); + } + +// private Collection getTopLeveFunctions(@NotNull GlobalSearchScope scope) { +// final BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCache(project, scope); +// final Collection keys = context.getKeys(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR); +// +// final List result = new ArrayList(); +// +// for (String namespaceKey : keys) { +// final NamespaceDescriptor namespace = context.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, namespaceKey); +// if (namespace != null) { +// final JetScope memberScope = namespace.getNamespaceType().getMemberScope(); +// final Collection allDescriptors = memberScope.getAllDescriptors(); +// +// for (DeclarationDescriptor descriptor : allDescriptors) { +// if (descriptor instanceof FunctionDescriptor) { +// FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; +// if (functionDescriptor.getReceiverParameter() == ReceiverDescriptor.NO_RECEIVER) { +// result.add(functionDescriptor); +// } +// } +// } +// } +// } +// +// return result; +// } @NotNull @Override diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java index f587a398ae8..63f25c24132 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java @@ -26,9 +26,20 @@ public final class DescriptorLookupConverter { private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler( JetFunctionInsertHandler.CaretPosition.IN_BRACKETS); + private DescriptorLookupConverter() {} + @NotNull - public static LookupElement createLookupElement(@NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { - LookupElementBuilder element = LookupElementBuilder.create(descriptor, descriptor.getName()); + public static LookupElement createLookupElement(@Nullable BindingContext context, @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { + + Object lookupObject = descriptor; + if (context != null) { + final PsiElement psiElement = context.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); + if (psiElement != null) { + lookupObject = new LookupPositionObject(psiElement); + } + } + + LookupElementBuilder element = LookupElementBuilder.create(lookupObject, descriptor.getName()); String typeText = ""; String tailText = ""; boolean tailTextGrayed = false; @@ -78,8 +89,6 @@ public final class DescriptorLookupConverter { @NotNull public static LookupElement createLookupElement(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) { - return createLookupElement(descriptor, bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal())); + return createLookupElement(bindingContext, descriptor, bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getOriginal())); } - - } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index 6c6535e4b4e..29138f87f0c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -2,27 +2,35 @@ package org.jetbrains.jet.plugin.completion; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.project.Project; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetQualifiedExpression; -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; -import org.jetbrains.jet.lang.psi.JetUserType; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.caches.JetCacheManager; +import org.jetbrains.jet.plugin.caches.JetShortNamesCache; +import org.jetbrains.jet.plugin.references.JetSimpleNameReference; import java.util.Collection; +import java.util.HashSet; /** * @author Nikolay Krasko */ public class JetCompletionContributor extends CompletionContributor { + + // A hack to avoid doubling of completion + final HashSet positions = new HashSet(); + public JetCompletionContributor() { extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new CompletionProvider() { @@ -30,50 +38,115 @@ public class JetCompletionContributor extends CompletionContributor { protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, final @NotNull CompletionResultSet result) { - if (result.getPrefixMatcher().getPrefix().isEmpty()) { - return; - } + synchronized (positions) { + positions.clear(); - final PsiElement position = parameters.getPosition(); - if (!(position.getContainingFile() instanceof JetFile)) { - return; - } + if (result.getPrefixMatcher().getPrefix().isEmpty()) { + return; + } - if (shouldRunClassNameCompletion(parameters, context)) { - addJavaClasses(parameters, result); - addJetClasses(result, position); + final PsiElement position = parameters.getPosition(); + if (!(position.getContainingFile() instanceof JetFile)) { + return; + } + + final JetSimpleNameReference jetReference = getJetReference(parameters); + if (jetReference != null) { + for (Object variant : jetReference.getVariants()) { + addReferenceVariant(result, variant); + } + } + + if (shouldRunClassNameCompletion(parameters)) { + addJavaClasses(parameters, result); + addJetClasses(result, position); + } + + if (shouldRunFunctionNameCompletion(parameters)) { + addJetTopLevelFunctions(result, position); + } + + result.stopHere(); } } }); } - private static void addJetClasses(CompletionResultSet result, PsiElement position) { - if (position.getParent() instanceof JetSimpleNameExpression) { - final JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) position.getParent(); - if (PsiTreeUtil.getParentOfType(nameExpression, JetQualifiedExpression.class) == null) { - Project project = position.getProject(); + private void addReferenceVariant(@NotNull CompletionResultSet result, @NotNull Object variant) { + if (variant instanceof LookupElement) { + addCompletionToResult(result, (LookupElement) variant); + } + else { + addCompletionToResult(result, LookupElementBuilder.create(variant.toString())); + } + } - final String referencedName = nameExpression.getReferencedName(); + private void addJetTopLevelFunctions(@NotNull CompletionResultSet result, @NotNull PsiElement position) { + String actualPrefix = getActualCompletionPrefix(position); + if (actualPrefix != null) { + final Project project = position.getProject(); - if (referencedName != null && referencedName.endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)) { - int lastPrefixIndex = referencedName.length() - - CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED.length(); - String actualPrefix = referencedName.substring(0, lastPrefixIndex); + final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache(); + final GlobalSearchScope scope = GlobalSearchScope.allScope(project); + final Collection functionNames = namesCache.getAllTopLevelFunctionNames(); - final Collection classDescriptors = - JetCacheManager.getInstance(project).getNamesCache().getClassDescriptors(); + for (String name : functionNames) { + if (name.contains(actualPrefix)) { + for (JetNamedFunction function : namesCache.getTopLevelFunctionsByName(name, scope)) { + String functionName = function.getName(); + String qualifiedName = function.getQualifiedName(); + assert functionName != null; + + final LookupElementBuilder lookup = LookupElementBuilder.create( + new LookupPositionObject(function), functionName); - for (ClassDescriptor descriptor : classDescriptors) { - if (descriptor.getName().startsWith(actualPrefix)) { - result.addElement(DescriptorLookupConverter.createLookupElement(descriptor, null)); + if (qualifiedName != null) { + lookup.setTailText(qualifiedName); } + + addCompletionToResult(result, lookup); } } } } } - private static void addJavaClasses(CompletionParameters parameters, final CompletionResultSet result) { + private void addJetClasses(@NotNull CompletionResultSet result, @NotNull PsiElement position) { + String actualPrefix = getActualCompletionPrefix(position); + if (actualPrefix != null) { + final Collection classDescriptors = + JetCacheManager.getInstance(position.getProject()).getNamesCache().getClassDescriptors(); + + for (ClassDescriptor descriptor : classDescriptors) { + if (descriptor.getName().startsWith(actualPrefix)) { + addCompletionToResult(result, DescriptorLookupConverter.createLookupElement(null, descriptor, null)); + } + } + } + } + + @Nullable + private static String getActualCompletionPrefix(@NotNull PsiElement position) { + if (position.getParent() instanceof JetSimpleNameExpression) { + final JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) position.getParent(); + + // Should be checked before call completion as pre-condition + assert (PsiTreeUtil.getParentOfType(nameExpression, JetQualifiedExpression.class) == null); + + final String referencedName = nameExpression.getReferencedName(); + + if (referencedName != null && referencedName.endsWith(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)) { + int lastPrefixIndex = referencedName.length() - + CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED.length(); + + return referencedName.substring(0, lastPrefixIndex); + } + } + + return null; + } + + private void addJavaClasses(@NotNull CompletionParameters parameters, @NotNull final CompletionResultSet result) { CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters)); @@ -81,14 +154,17 @@ public class JetCompletionContributor extends CompletionContributor { parameters, tempResult), parameters.getInvocationCount() <= 1, new Consumer() { @Override - public void consume(LookupElement element) { - result.addElement(element); - + public void consume(@NotNull LookupElement element) { + addCompletionToResult(result, element); } }); } - private static boolean shouldRunClassNameCompletion(@NotNull CompletionParameters parameters, ProcessingContext context) { + private static boolean shouldRunFunctionNameCompletion(@NotNull CompletionParameters parameters) { + return shouldRunClassNameCompletion(parameters); + } + + private static boolean shouldRunClassNameCompletion(@NotNull CompletionParameters parameters) { final PsiElement element = parameters.getPosition(); if (parameters.getInvocationCount() > 1) { @@ -113,8 +189,40 @@ public class JetCompletionContributor extends CompletionContributor { return false; } - @Override - public void beforeCompletion(@NotNull CompletionInitializationContext context) { - super.beforeCompletion(context); //To change body of overridden methods use File | Settings | File Templates. + @Nullable + private static JetSimpleNameReference getJetReference(@NotNull CompletionParameters parameters) { + final PsiElement element = parameters.getPosition(); + if (element.getParent() != null) { + final PsiElement parent = element.getParent(); + PsiReference[] references = parent.getReferences(); + + if (references.length != 0) { + for (PsiReference reference : references) { + if (reference instanceof JetSimpleNameReference) { + return (JetSimpleNameReference) reference; + } + } + } +// if (reference == null && parent instanceof CompositeElement) { +// reference = ((CompositeElement) parent).getPsi().getReference(); +// } + } + + return null; + } + + private void addCompletionToResult(@NotNull final CompletionResultSet result, LookupElement element) { + if (element.getObject() instanceof LookupPositionObject) { + final LookupPositionObject positionObject = (LookupPositionObject) element.getObject(); + + if (positions.contains(positionObject)) { + return; + } + else { + positions.add(positionObject); + } + } + + result.addElement(element); } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LookupPositionObject.java b/idea/src/org/jetbrains/jet/plugin/completion/LookupPositionObject.java new file mode 100644 index 00000000000..0fc9ca6edcc --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupPositionObject.java @@ -0,0 +1,43 @@ +package org.jetbrains.jet.plugin.completion; + +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +/** + * A hack decision to avoid double completion from different sources. + * + * @author Nikolay Krasko + */ +public class LookupPositionObject { + private final Pair position; + + public LookupPositionObject(@NotNull PsiElement psiElement) { + + PsiFile file = psiElement.getContainingFile(); + String fileName = file != null ? file.getName() : null; + + position = new Pair(fileName, psiElement.getTextOffset()); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (obj.getClass() != getClass()) { + return false; + } + + return Comparing.equal(position, ((LookupPositionObject) obj).position); + } + + public int hashCode() { + return position.hashCode(); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java similarity index 76% rename from idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassFix.java rename to idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index 674bbfae967..44abf572baa 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.plugin.quickfix; import com.google.common.base.Function; +import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Sets; @@ -23,27 +24,25 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.actions.JetAddImportAction; import org.jetbrains.jet.plugin.caches.JetCacheManager; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; /** * Check possibility and perform fix for unresolved references. * * @author Nikolay Krasko */ -public class ImportClassFix extends JetHintAction implements HighPriorityAction { +public class ImportClassAndFunFix extends JetHintAction implements HighPriorityAction { @NotNull private final List suggestions; - public ImportClassFix(@NotNull JetSimpleNameExpression element) { + public ImportClassAndFunFix(@NotNull JetSimpleNameExpression element) { super(element); suggestions = computeSuggestions(element); } @@ -54,7 +53,39 @@ public class ImportClassFix extends JetHintAction imple return Collections.emptyList(); } - return getClassNames(element, file.getProject()); + final ArrayList result = new ArrayList(); + result.addAll(getClassNames(element, file.getProject())); + result.addAll(getJetTopLevelFunctions(element, file.getProject())); + + return result; + } + + private static Collection getJetTopLevelFunctions(@NotNull JetSimpleNameExpression expression, @NotNull Project project) { + final String referenceName = expression.getReferencedName(); + + if (referenceName == null) { + return Collections.emptyList(); + } + + final Collection namedFunctions = + JetCacheManager.getInstance(project).getNamesCache().getTopLevelFunctionsByName( + referenceName, GlobalSearchScope.allScope(project)); + + final Collection nullableNames = + Collections2.transform(Lists.newArrayList(namedFunctions), new Function() { + @Nullable + @Override + public String apply(@Nullable JetNamedFunction jetFunction) { + return jetFunction != null ? jetFunction.getQualifiedName() : null; + } + }); + + return Collections2.filter(nullableNames, new Predicate() { + @Override + public boolean apply(@Nullable String fqn) { + return fqn != null && !fqn.isEmpty(); + } + }); } /* @@ -79,7 +110,7 @@ public class ImportClassFix extends JetHintAction imple private static Collection getJavaClasses(@NotNull final String typeName, @NotNull Project project, final GlobalSearchScope scope) { PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); - PsiClass[] classes = cache.getClassesByName(typeName, new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { + PsiClass[] classes = cache.getClassesByName(typeName, new DelegatingGlobalSearchScope(scope) { @Override public boolean contains(@NotNull VirtualFile file) { return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE; @@ -166,7 +197,7 @@ public class ImportClassFix extends JetHintAction imple // There could be different psi elements (i.e. JetArrayAccessExpression), but we can fix only JetSimpleNameExpression case if (diagnostic.getPsiElement() instanceof JetSimpleNameExpression) { JetSimpleNameExpression psiElement = (JetSimpleNameExpression) diagnostic.getPsiElement(); - return new ImportClassFix(psiElement); + return new ImportClassAndFunFix(psiElement); } return null; diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 26e14ddf8a9..3230d56c57d 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -108,7 +108,7 @@ public class QuickFixes { add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory); add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory); - JetIntentionActionFactory unresolvedReferenceFactory = ImportClassFix.createFactory(); + JetIntentionActionFactory unresolvedReferenceFactory = ImportClassAndFunFix.createFactory(); add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory); add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory()); diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index d5b61a48dd6..a66a2833fca 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -20,7 +20,7 @@ import java.util.List; /** * @author yole */ -class JetSimpleNameReference extends JetPsiReference { +public class JetSimpleNameReference extends JetPsiReference { private final JetSimpleNameExpression myExpression; diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetExtensionFunctionNameIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetExtensionFunctionNameIndex.java new file mode 100644 index 00000000000..ac57a8330cd --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetExtensionFunctionNameIndex.java @@ -0,0 +1,21 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.psi.stubs.StringStubIndexExtension; +import com.intellij.psi.stubs.StubIndexKey; +import org.jetbrains.jet.lang.psi.JetNamedFunction; + +/** + * @author Nikolay Krasko + */ +public class JetExtensionFunctionNameIndex extends StringStubIndexExtension { + private static final JetExtensionFunctionNameIndex instance = new JetExtensionFunctionNameIndex(); + + public static JetExtensionFunctionNameIndex getInstance() { + return instance; + } + + @Override + public StubIndexKey getKey() { + return JetIndexKeys.EXTENSION_FUNCTION_SHORT_NAME_KEY; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java index fed0fe7e5c8..48be0a04280 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexKeys.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.plugin.stubindex; import com.intellij.psi.stubs.StubIndexKey; import org.jetbrains.jet.lang.psi.JetClassOrObject; -import org.jetbrains.jet.lang.psi.JetFunction; +import org.jetbrains.jet.lang.psi.JetNamedFunction; /** * @author Nikolay Krasko @@ -10,11 +10,11 @@ import org.jetbrains.jet.lang.psi.JetFunction; public interface JetIndexKeys { StubIndexKey SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.class.shortName"); StubIndexKey FQN_KEY = StubIndexKey.createIndexKey("jet.fqn"); - - StubIndexKey TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); -// StubIndexKey TOP_LEVEL_FUNCTION_FQN_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); -// StubIndexKey PACKAGE_OBJECT_KEY = StubIndexKey.createIndexKey("jet.package.object.fqn"); -// StubIndexKey EXTENSION_FUNCTION_TO_TYPE_FQN = StubIndexKey.createIndexKey("jet.extension.function.to.type.fqn"); + StubIndexKey TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name"); + StubIndexKey TOP_LEVEL_FUNCTION_FQNAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.fqname"); + + StubIndexKey EXTENSION_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.extension.function.short.name"); + StubIndexKey EXTENSION_FUNCTION_FQNAME_KEY = StubIndexKey.createIndexKey("jet.top.level.extension.function.fqname"); } diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java deleted file mode 100644 index 773389dc288..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/JetIndexedStubElementFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.jetbrains.jet.plugin.stubindex; - -import com.intellij.psi.stubs.IndexSink; -import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; -import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; -import org.jetbrains.jet.lang.psi.stubs.elements.JetClassElementType; -import org.jetbrains.jet.lang.psi.stubs.elements.JetFunctionElementType; -import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementFactory; - -/** - * @author Nikolay Krasko - */ -public class JetIndexedStubElementFactory implements JetStubElementFactory { - @Override - public JetClassElementType getClassElementType() { - return new JetClassElementType("CLASS") { - @Override - public void indexStub(PsiJetClassStub stub, IndexSink sink) { - String name = stub.getName(); - if (name != null) { - sink.occurrence(JetIndexKeys.SHORT_NAME_KEY, name); - } - } - }; - } - - @Override - public JetFunctionElementType getFunctionElementType() { - return new JetFunctionElementType("FUN") { - @Override - public void indexStub(PsiJetFunctionStub stub, IndexSink sink) { - String name = stub.getName(); - // TODO: Check that function defined in top level - if (name != null) { - sink.occurrence(JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY, name); - } - } - }; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java index bb167dfc667..02dc55a1b86 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/JetShortFunctionNameIndex.java @@ -5,27 +5,27 @@ 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.JetFunction; +import org.jetbrains.jet.lang.psi.JetNamedFunction; import java.util.Collection; /** * @author Nikolay Krasko */ -public class JetShortFunctionNameIndex extends StringStubIndexExtension { - private static final JetShortClassNameIndex ourInstance = new JetShortClassNameIndex(); +public class JetShortFunctionNameIndex extends StringStubIndexExtension { + private static final JetShortFunctionNameIndex ourInstance = new JetShortFunctionNameIndex(); - public static JetShortClassNameIndex getInstance() { + public static JetShortFunctionNameIndex getInstance() { return ourInstance; } @Override - public StubIndexKey getKey() { + public StubIndexKey getKey() { return JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY; } @Override - public Collection get(final String s, final Project project, @NotNull final GlobalSearchScope scope) { - return super.get(s, project, new JetSourceFilterScope(scope)); + 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 new file mode 100644 index 00000000000..6874943d167 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/StubIndexServiceImpl.java @@ -0,0 +1,35 @@ +package org.jetbrains.jet.plugin.stubindex; + +import com.intellij.psi.stubs.IndexSink; +import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; +import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; +import org.jetbrains.jet.lang.psi.stubs.elements.StubIndexService; + +/** + * @author Nikolay Krasko + */ +public class StubIndexServiceImpl implements StubIndexService { + + @Override + public void indexClass(PsiJetClassStub stub, IndexSink sink) { + String name = stub.getName(); + if (name != null) { + sink.occurrence(JetIndexKeys.SHORT_NAME_KEY, name); + } + } + + @Override + public void indexFunction(PsiJetFunctionStub stub, IndexSink sink) { + String name = stub.getName(); + if (name != null) { + if (!stub.isExtension()) { + if (stub.isTopLevel()) { + sink.occurrence(JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY, name); + } + } + else { + sink.occurrence(JetIndexKeys.EXTENSION_FUNCTION_SHORT_NAME_KEY, name); + } + } + } +} diff --git a/idea/testData/completion/basic/VariableClassName.kt b/idea/testData/completion/basic/VariableClassName.kt index 38c1068b400..c382c630cdd 100644 --- a/idea/testData/completion/basic/VariableClassName.kt +++ b/idea/testData/completion/basic/VariableClassName.kt @@ -1,3 +1,5 @@ +package some; + open class MyClass() { } diff --git a/idea/testData/quickfix/autoImports/afterFunctionImport.kt b/idea/testData/quickfix/autoImports/afterFunctionImport.kt new file mode 100644 index 00000000000..7260291843f --- /dev/null +++ b/idea/testData/quickfix/autoImports/afterFunctionImport.kt @@ -0,0 +1,8 @@ +// "Import Class" "true" +package functionimporttest + +import functionimporttest.data.someTestFun + +fun functionImportTest() { + someTestFun() +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/beforeFunctionImport.Data.Sample.kt b/idea/testData/quickfix/autoImports/beforeFunctionImport.Data.Sample.kt new file mode 100644 index 00000000000..a40093b4260 --- /dev/null +++ b/idea/testData/quickfix/autoImports/beforeFunctionImport.Data.Sample.kt @@ -0,0 +1,7 @@ +package functionimporttest.data + +fun String.someTestFun() { +} + +fun someTestFun() { +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/beforeFunctionImport.Main.kt b/idea/testData/quickfix/autoImports/beforeFunctionImport.Main.kt new file mode 100644 index 00000000000..c3cbf9621d9 --- /dev/null +++ b/idea/testData/quickfix/autoImports/beforeFunctionImport.Main.kt @@ -0,0 +1,6 @@ +// "Import Class" "true" +package functionimporttest + +fun functionImportTest() { + someTestFun() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java index ad0ed374b78..26b1d11d6a2 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/FunctionsHandlerTest.java @@ -26,11 +26,8 @@ public class FunctionsHandlerTest extends LightCompletionTestCase { checkResultByFile("SingleBrackets.kt.after"); } - // public void - @Override protected String getTestDataPath() { - return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + - File.separator; + return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + File.separator; } }