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
This commit is contained in:
Nikolay Krasko
2012-01-31 14:10:08 +04:00
parent dbbd4c6902
commit 2826db7d9a
37 changed files with 569 additions and 270 deletions
@@ -1110,7 +1110,8 @@ public class JavaDescriptorResolver {
} }
@NotNull @NotNull
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor descriptor, @NotNull PsiClass psiClass, @NotNull String methodName, boolean staticMembers) { public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor descriptor, @NotNull PsiClass psiClass,
@NotNull String methodName, boolean staticMembers) {
ResolverScopeData resolverScopeData = getResolverScopeData(descriptor, new PsiClassWrapper(psiClass)); ResolverScopeData resolverScopeData = getResolverScopeData(descriptor, new PsiClassWrapper(psiClass));
@@ -8,12 +8,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Set;
/** /**
* @author abreslav * @author abreslav
@@ -16,27 +16,14 @@ import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeType; import org.jetbrains.jet.JetNodeType;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.psi.JetFile; 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.JetStubElementType;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
import org.jetbrains.jet.lexer.JetLexer; import org.jetbrains.jet.lexer.JetLexer;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
public class JetParserDefinition implements ParserDefinition { 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() { public JetParserDefinition() {
if (!ApplicationManager.getApplication().isCommandLine()) { if (!ApplicationManager.getApplication().isCommandLine()) {
} }
@@ -52,9 +39,7 @@ public class JetParserDefinition implements ParserDefinition {
} }
public IFileElementType getFileNodeType() { public IFileElementType getFileNodeType() {
// TODO (stubs) return JetStubElementTypes.FILE;
return JetNodeTypes.JET_FILE;
// return JetStubElementTypes.FILE;
} }
@NotNull @NotNull
@@ -7,6 +7,8 @@ import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider; import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubTree;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.JetNodeTypes;
@@ -58,4 +60,19 @@ public class JetFile extends PsiFileBase {
visitor.visitFile(this); 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.
}
} }
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.StubBasedPsiElement; import com.intellij.psi.StubBasedPsiElement;
import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.IStubElementType;
import org.jetbrains.annotations.NotNull; 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.PsiJetFunctionStub;
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -66,11 +67,37 @@ public class JetNamedFunction extends JetFunction implements StubBasedPsiElement
return this; 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 @Override
public IStubElementType getElementType() { public IStubElementType getElementType() {
return JetStubElementTypes.FUNCTION; return JetStubElementTypes.FUNCTION;
} }
@Override @Override
public PsiJetFunctionStub<?> getStub() { public PsiJetFunctionStub<?> getStub() {
// TODO (stubs) // TODO (stubs)
@@ -12,11 +12,17 @@ public interface PsiJetFunctionStub <T extends JetFunction> extends StubElement<
@Nullable @Nullable
String getName(); String getName();
boolean isDeclaration(); /**
* Is function defined in directly in package.
* @return
*/
boolean isTopLevel();
/**
* Does function extends some type.
*/
boolean isExtension();
@NotNull @NotNull
String[] getAnnotations(); String[] getAnnotations();
@NotNull
String getReturnTypeText();
} }
@@ -13,17 +13,16 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub; import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub;
import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetClassStubImpl; import org.jetbrains.jet.lang.psi.stubs.impl.PsiJetClassStubImpl;
import org.jetbrains.jet.plugin.JetLanguage;
import java.io.IOException; import java.io.IOException;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public abstract class JetClassElementType extends JetStubElementType<PsiJetClassStub, JetClass> { public class JetClassElementType extends JetStubElementType<PsiJetClassStub, JetClass> {
public JetClassElementType(@NotNull @NonNls String debugName) { public JetClassElementType(@NotNull @NonNls String debugName) {
super(debugName, JetLanguage.INSTANCE); super(debugName);
} }
@Override @Override
@@ -33,7 +32,6 @@ public abstract class JetClassElementType extends JetStubElementType<PsiJetClass
@Override @Override
public JetClass createPsi(@NotNull PsiJetClassStub stub) { public JetClass createPsi(@NotNull PsiJetClassStub stub) {
// TODO: Don't work for kotlin classes
// return getPsiFactory(stub).createClass(stub); // return getPsiFactory(stub).createClass(stub);
return null; return null;
} }
@@ -45,7 +43,7 @@ public abstract class JetClassElementType extends JetStubElementType<PsiJetClass
@Override @Override
public PsiJetClassStub createStub(@NotNull JetClass psi, StubElement parentStub) { public PsiJetClassStub createStub(@NotNull JetClass psi, StubElement parentStub) {
return null; //To change body of implemented methods use File | Settings | File Templates. return new PsiJetClassStubImpl(JetStubElementTypes.CLASS, parentStub, psi.getName(), psi.getName());
} }
@Override @Override
@@ -66,5 +64,7 @@ public abstract class JetClassElementType extends JetStubElementType<PsiJetClass
} }
@Override @Override
public abstract void indexStub(PsiJetClassStub stub, IndexSink sink); public void indexStub(PsiJetClassStub stub, IndexSink sink) {
StubIndexServiceFactory.getInstance().indexClass(stub, sink);
}
} }
@@ -1,28 +0,0 @@
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 class JetFakeStubElementFactory implements JetStubElementFactory {
@Override
public JetClassElementType getClassElementType() {
return new JetClassElementType("CLASS") {
@Override
public void indexStub(PsiJetClassStub stub, IndexSink sink) {
}
};
}
@Override
public JetFunctionElementType getFunctionElementType() {
return new JetFunctionElementType("FUN") {
@Override
public void indexStub(PsiJetFunctionStub stub, IndexSink sink) {
}
};
}
}
@@ -1,7 +1,5 @@
package org.jetbrains.jet.lang.psi.stubs.elements; package org.jetbrains.jet.lang.psi.stubs.elements;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.StubBuilder; import com.intellij.psi.StubBuilder;
import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
@@ -35,21 +33,6 @@ public class JetFileElementType extends IStubFileElementType<PsiJetFileStub> {
return STUB_VERSION; 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 @Override
public String getExternalId() { public String getExternalId() {
return "jet.FILE"; return "jet.FILE";
@@ -17,7 +17,7 @@ public class JetFileStubBuilder extends DefaultStubBuilder {
if (!(file instanceof JetFile)) return super.createStubForFile(file); if (!(file instanceof JetFile)) return super.createStubForFile(file);
JetFile jetFile = (JetFile) file; JetFile jetFile = (JetFile) file;
// TODO (stubs): // TODO (stubs):
String packageName = "default"; String packageName = "default";
@@ -3,29 +3,31 @@ package org.jetbrains.jet.lang.psi.stubs.elements;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterAST; import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode; import com.intellij.lang.LighterASTNode;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream; import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; 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.JetNamedFunction;
import org.jetbrains.jet.lang.psi.stubs.PsiJetFileStub;
import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; 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; import java.io.IOException;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public abstract class JetFunctionElementType extends JetStubElementType<PsiJetFunctionStub, JetFunction> { public class JetFunctionElementType extends JetStubElementType<PsiJetFunctionStub, JetNamedFunction> {
public JetFunctionElementType(@NotNull @NonNls String debugName) { public JetFunctionElementType(@NotNull @NonNls String debugName) {
super(debugName, JetLanguage.INSTANCE); super(debugName);
} }
@Override @Override
public JetFunction createPsiFromAst(@NotNull ASTNode node) { public JetNamedFunction createPsiFromAst(@NotNull ASTNode node) {
return new JetNamedFunction(node); return new JetNamedFunction(node);
} }
@@ -35,22 +37,38 @@ public abstract class JetFunctionElementType extends JetStubElementType<PsiJetFu
} }
@Override @Override
public JetFunction createPsi(@NotNull PsiJetFunctionStub stub) { public JetNamedFunction createPsi(@NotNull PsiJetFunctionStub stub) {
return null; //To change body of implemented methods use File | Settings | File Templates. return null; //To change body of implemented methods use File | Settings | File Templates.
} }
@Override @Override
public PsiJetFunctionStub createStub(@NotNull JetFunction psi, StubElement parentStub) { public PsiJetFunctionStub createStub(@NotNull JetNamedFunction psi, StubElement parentStub) {
return null; //To change body of implemented methods use File | Settings | File Templates. final boolean isTopLevel = parentStub instanceof PsiJetFileStub;
final boolean isExtension = psi.getReceiverTypeRef() != null;
return new PsiJetFunctionStubImpl(
JetStubElementTypes.FUNCTION, parentStub, psi.getName(),
isTopLevel, isExtension);
} }
@Override @Override
public void serialize(PsiJetFunctionStub stub, StubOutputStream dataStream) throws IOException { public void serialize(PsiJetFunctionStub stub, StubOutputStream dataStream) throws IOException {
//To change body of implemented methods use File | Settings | File Templates. dataStream.writeName(stub.getName());
dataStream.writeBoolean(stub.isTopLevel());
dataStream.writeBoolean(stub.isExtension());
} }
@Override @Override
public PsiJetFunctionStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { public PsiJetFunctionStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException {
return null; //To change body of implemented methods use File | Settings | File Templates. final StringRef name = dataStream.readName();
final boolean isTopLevel = dataStream.readBoolean();
final boolean isExtension = dataStream.readBoolean();
return new PsiJetFunctionStubImpl(JetStubElementTypes.FUNCTION, parentStub, name, isTopLevel, isExtension);
}
@Override
public void indexStub(PsiJetFunctionStub stub, IndexSink sink) {
StubIndexServiceFactory.getInstance().indexFunction(stub, sink);
} }
} }
@@ -1,9 +0,0 @@
package org.jetbrains.jet.lang.psi.stubs.elements;
/**
* @author Nikolay Krasko
*/
public interface JetStubElementFactory {
JetClassElementType getClassElementType();
JetFunctionElementType getFunctionElementType();
}
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.psi.stubs.elements; package org.jetbrains.jet.lang.psi.stubs.elements;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.java.stubs.StubPsiFactory; import com.intellij.psi.impl.java.stubs.StubPsiFactory;
@@ -10,7 +9,7 @@ import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.plugin.JetLanguage;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
@@ -18,12 +17,10 @@ import org.jetbrains.annotations.Nullable;
public abstract class JetStubElementType<StubT extends StubElement, PsiT extends PsiElement> public abstract class JetStubElementType<StubT extends StubElement, PsiT extends PsiElement>
extends ILightStubElementType<StubT, PsiT> { extends ILightStubElementType<StubT, PsiT> {
public JetStubElementType(@NotNull @NonNls String debugName, @Nullable Language language) { public JetStubElementType(@NotNull @NonNls String debugName) {
super(debugName, language); super(debugName, JetLanguage.INSTANCE);
} }
public abstract PsiT createPsiFromAst(@NotNull ASTNode node); public abstract PsiT createPsiFromAst(@NotNull ASTNode node);
protected StubPsiFactory getPsiFactory(StubT stub) { protected StubPsiFactory getPsiFactory(StubT stub) {
@@ -1,13 +1,11 @@
package org.jetbrains.jet.lang.psi.stubs.elements; package org.jetbrains.jet.lang.psi.stubs.elements;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public interface JetStubElementTypes { public interface JetStubElementTypes {
JetFileElementType FILE = new JetFileElementType(); JetFileElementType FILE = new JetFileElementType();
JetClassElementType CLASS = JetParserDefinition.getStubElementTypeFactory().getClassElementType(); JetClassElementType CLASS = new JetClassElementType("CLASS");
JetFunctionElementType FUNCTION = JetParserDefinition.getStubElementTypeFactory().getFunctionElementType(); JetFunctionElementType FUNCTION = new JetFunctionElementType("FUN");
} }
@@ -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);
}
@@ -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;
}
}
@@ -3,7 +3,9 @@ package org.jetbrains.jet.lang.psi.stubs.impl;
import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetFunction;
import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub; import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub;
@@ -11,49 +13,44 @@ import org.jetbrains.jet.lang.psi.stubs.PsiJetFunctionStub;
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public class PsiJetFunctionStubImpl extends StubBase<JetFunction> implements PsiJetFunctionStub<JetFunction> { public class PsiJetFunctionStubImpl extends StubBase<JetFunction> implements PsiJetFunctionStub<JetFunction> {
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( public PsiJetFunctionStubImpl(@NotNull IStubElementType elementType, @NotNull StubElement parent,
// Jet type, @Nullable StringRef nameRef, boolean isTopLevel, boolean isExtension) {
// final StubElement parent, super(parent, elementType);
// final String qualifiedName,
// final String name) { this.nameRef = nameRef;
// this.isTopLevel = isTopLevel;
// this(type, parent, StringRef.fromString(qualifiedName), StringRef.fromString(name)); this.isExtension = isExtension;
// } }
//
// public PsiJetFunctionStubImpl(
// JetClassElementType type,
// final StubElement parent,
// final StringRef qualifiedName,
// final StringRef name) {
//
// super(parent, type);
// this.qualifiedName = qualifiedName;
// this.name = name;
// }
@Override @Override
public String getName() { public String getName() {
return null; //To change body of implemented methods use File | Settings | File Templates. return StringRef.toString(nameRef);
} }
@Override @Override
public boolean isDeclaration() { public boolean isTopLevel() {
return false; //To change body of implemented methods use File | Settings | File Templates. return isTopLevel;
}
@Override
public boolean isExtension() {
return isExtension;
} }
@NotNull @NotNull
@Override @Override
public String[] getAnnotations() { public String[] getAnnotations() {
return new String[0]; //To change body of implemented methods use File | Settings | File Templates. // TODO (stubs)
} return new String[0];
@NotNull
@Override
public String getReturnTypeText() {
return null; //To change body of implemented methods use File | Settings | File Templates.
} }
} }
+17 -6
View File
@@ -4,9 +4,6 @@
<version>@snapshot@</version> <version>@snapshot@</version>
<vendor>JetBrains</vendor> <vendor>JetBrains</vendor>
<application-components>
</application-components>
<project-components> <project-components>
<component> <component>
<implementation-class>org.jetbrains.jet.plugin.compiler.JetCompilerManager</implementation-class> <implementation-class>org.jetbrains.jet.plugin.compiler.JetCompilerManager</implementation-class>
@@ -44,6 +41,9 @@
</actions> </actions>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="org.jetbrains.jet.lang.psi.stubs.elements.StubIndexService"
serviceImplementation="org.jetbrains.jet.plugin.stubindex.StubIndexServiceImpl" />
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/> <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<internalFileTemplate name="Kotlin File"/> <internalFileTemplate name="Kotlin File"/>
@@ -57,13 +57,18 @@
<lang.foldingBuilder language="jet" implementationClass="org.jetbrains.jet.plugin.JetFoldingBuilder"/> <lang.foldingBuilder language="jet" implementationClass="org.jetbrains.jet.plugin.JetFoldingBuilder"/>
<lang.formatter language="jet" implementationClass="org.jetbrains.jet.plugin.formatter.JetFormattingModelBuilder"/> <lang.formatter language="jet" implementationClass="org.jetbrains.jet.plugin.formatter.JetFormattingModelBuilder"/>
<lang.findUsagesProvider language="jet" implementationClass="org.jetbrains.jet.plugin.findUsages.JetFindUsagesProvider"/> <lang.findUsagesProvider language="jet" implementationClass="org.jetbrains.jet.plugin.findUsages.JetFindUsagesProvider"/>
<psi.referenceContributor language="jet" implementation="org.jetbrains.jet.plugin.references.JetReferenceContributor"/>
<codeInsight.parameterInfo language="jet" implementationClass="org.jetbrains.jet.plugin.parameterInfo.JetFunctionParameterInfoHandler"/> <codeInsight.parameterInfo language="jet" implementationClass="org.jetbrains.jet.plugin.parameterInfo.JetFunctionParameterInfoHandler"/>
<completion.contributor language="jet" id="JetKeywordCompletionContributor" order="first"
implementationClass="org.jetbrains.jet.plugin.completion.JetKeywordCompletionContributor"/>
<completion.contributor language="jet" id="JetCompletionContributor"
implementationClass="org.jetbrains.jet.plugin.completion.JetCompletionContributor"/>
<completion.contributor language="jet" implementationClass="org.jetbrains.jet.plugin.completion.GlobalMemberCompletionContributor"/> <completion.contributor language="jet" implementationClass="org.jetbrains.jet.plugin.completion.GlobalMemberCompletionContributor"/>
<completion.contributor language="jet" implementationClass="org.jetbrains.jet.plugin.completion.JetKeywordCompletionContributor"/>
<completion.contributor language="jet" implementationClass="org.jetbrains.jet.plugin.completion.JetCompletionContributor"/> <psi.referenceContributor language="jet" order="after JetCompletionContributor" implementation="org.jetbrains.jet.plugin.references.JetReferenceContributor"/>
<liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Generic"/> <liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Generic"/>
<liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Namespace"/> <liveTemplateContext implementation="org.jetbrains.jet.plugin.liveTemplates.JetTemplateContextType$Namespace"/>
@@ -91,6 +96,12 @@
<java.elementFinder implementation="org.jetbrains.jet.asJava.JavaElementFinder"/> <java.elementFinder implementation="org.jetbrains.jet.asJava.JavaElementFinder"/>
<java.shortNamesCache implementation="org.jetbrains.jet.plugin.caches.JetShortNamesCache"/> <java.shortNamesCache implementation="org.jetbrains.jet.plugin.caches.JetShortNamesCache"/>
<stubElementTypeHolder class="org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetShortClassNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetFullClassNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetShortFunctionNameIndex"/>
<stubIndex implementation="org.jetbrains.jet.plugin.stubindex.JetExtensionFunctionNameIndex"/>
<editorNotificationProvider implementation="org.jetbrains.jet.plugin.quickfix.ConfigureKotlinLibraryNotificationProvider"/> <editorNotificationProvider implementation="org.jetbrains.jet.plugin.quickfix.ConfigureKotlinLibraryNotificationProvider"/>
<psi.treeChangePreprocessor implementation="org.jetbrains.jet.asJava.JetCodeBlockModificationListener"/> <psi.treeChangePreprocessor implementation="org.jetbrains.jet.asJava.JetCodeBlockModificationListener"/>
@@ -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());
// }
}
@@ -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(); PsiDocumentManager.getInstance(project).commitAllDocuments();
CommandProcessor.getInstance().executeCommand(project, new Runnable() { CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@@ -16,8 +16,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass; 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.lang.resolve.BindingContext;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; 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.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -107,6 +110,45 @@ public class JetShortNamesCache extends PsiShortNamesCache {
} }
}); });
} }
public Collection<JetNamedFunction> getAllExtensionFunctionsByName(@NotNull String name, @NotNull GlobalSearchScope scope) {
return JetExtensionFunctionNameIndex.getInstance().get(name, project, scope);
}
@NotNull
public Collection<String> getAllTopLevelFunctionNames() {
return JetShortFunctionNameIndex.getInstance().getAllKeys(project);
}
public Collection<JetNamedFunction> getTopLevelFunctionsByName(final @NotNull String name, @NotNull GlobalSearchScope scope) {
return JetShortFunctionNameIndex.getInstance().get(name, project, scope);
}
// private Collection<FunctionDescriptor> getTopLeveFunctions(@NotNull GlobalSearchScope scope) {
// final BindingContext context = WholeProjectAnalyzerFacade.analyzeProjectWithCache(project, scope);
// final Collection<String> keys = context.getKeys(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR);
//
// final List<FunctionDescriptor> result = new ArrayList<FunctionDescriptor>();
//
// 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<DeclarationDescriptor> 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 @NotNull
@Override @Override
@@ -26,9 +26,20 @@ public final class DescriptorLookupConverter {
private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler( private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler(
JetFunctionInsertHandler.CaretPosition.IN_BRACKETS); JetFunctionInsertHandler.CaretPosition.IN_BRACKETS);
private DescriptorLookupConverter() {}
@NotNull @NotNull
public static LookupElement createLookupElement(@NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { public static LookupElement createLookupElement(@Nullable BindingContext context, @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) {
LookupElementBuilder element = LookupElementBuilder.create(descriptor, descriptor.getName());
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 typeText = "";
String tailText = ""; String tailText = "";
boolean tailTextGrayed = false; boolean tailTextGrayed = false;
@@ -78,8 +89,6 @@ public final class DescriptorLookupConverter {
@NotNull @NotNull
public static LookupElement createLookupElement(@NotNull BindingContext bindingContext, @NotNull DeclarationDescriptor descriptor) { 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()));
} }
} }
@@ -2,27 +2,35 @@ package org.jetbrains.jet.plugin.completion;
import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.patterns.PlatformPatterns; import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.PsiElement; 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.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer; import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext; import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.*;
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.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.caches.JetCacheManager; 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.Collection;
import java.util.HashSet;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public class JetCompletionContributor extends CompletionContributor { public class JetCompletionContributor extends CompletionContributor {
// A hack to avoid doubling of completion
final HashSet<LookupPositionObject> positions = new HashSet<LookupPositionObject>();
public JetCompletionContributor() { public JetCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), extend(CompletionType.BASIC, PlatformPatterns.psiElement(),
new CompletionProvider<CompletionParameters>() { new CompletionProvider<CompletionParameters>() {
@@ -30,50 +38,115 @@ public class JetCompletionContributor extends CompletionContributor {
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context,
final @NotNull CompletionResultSet result) { final @NotNull CompletionResultSet result) {
if (result.getPrefixMatcher().getPrefix().isEmpty()) { synchronized (positions) {
return; positions.clear();
}
final PsiElement position = parameters.getPosition(); if (result.getPrefixMatcher().getPrefix().isEmpty()) {
if (!(position.getContainingFile() instanceof JetFile)) { return;
return; }
}
if (shouldRunClassNameCompletion(parameters, context)) { final PsiElement position = parameters.getPosition();
addJavaClasses(parameters, result); if (!(position.getContainingFile() instanceof JetFile)) {
addJetClasses(result, position); 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) { private void addReferenceVariant(@NotNull CompletionResultSet result, @NotNull Object variant) {
if (position.getParent() instanceof JetSimpleNameExpression) { if (variant instanceof LookupElement) {
final JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) position.getParent(); addCompletionToResult(result, (LookupElement) variant);
if (PsiTreeUtil.getParentOfType(nameExpression, JetQualifiedExpression.class) == null) { }
Project project = position.getProject(); 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)) { final JetShortNamesCache namesCache = JetCacheManager.getInstance(position.getProject()).getNamesCache();
int lastPrefixIndex = referencedName.length() - final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED.length(); final Collection<String> functionNames = namesCache.getAllTopLevelFunctionNames();
String actualPrefix = referencedName.substring(0, lastPrefixIndex);
final Collection<ClassDescriptor> classDescriptors = for (String name : functionNames) {
JetCacheManager.getInstance(project).getNamesCache().getClassDescriptors(); 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 (qualifiedName != null) {
if (descriptor.getName().startsWith(actualPrefix)) { lookup.setTailText(qualifiedName);
result.addElement(DescriptorLookupConverter.createLookupElement(descriptor, null));
} }
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<ClassDescriptor> 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)); CompletionResultSet tempResult = result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
@@ -81,14 +154,17 @@ public class JetCompletionContributor extends CompletionContributor {
parameters, tempResult), parameters.getInvocationCount() <= 1, new Consumer<LookupElement>() { parameters, tempResult), parameters.getInvocationCount() <= 1, new Consumer<LookupElement>() {
@Override @Override
public void consume(LookupElement element) { public void consume(@NotNull LookupElement element) {
result.addElement(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(); final PsiElement element = parameters.getPosition();
if (parameters.getInvocationCount() > 1) { if (parameters.getInvocationCount() > 1) {
@@ -113,8 +189,40 @@ public class JetCompletionContributor extends CompletionContributor {
return false; return false;
} }
@Override @Nullable
public void beforeCompletion(@NotNull CompletionInitializationContext context) { private static JetSimpleNameReference getJetReference(@NotNull CompletionParameters parameters) {
super.beforeCompletion(context); //To change body of overridden methods use File | Settings | File Templates. 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);
} }
} }
@@ -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<String, Integer> position;
public LookupPositionObject(@NotNull PsiElement psiElement) {
PsiFile file = psiElement.getContainingFile();
String fileName = file != null ? file.getName() : null;
position = new Pair<String, Integer>(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();
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jet.plugin.quickfix; package org.jetbrains.jet.plugin.quickfix;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2; import com.google.common.collect.Collections2;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@@ -23,27 +24,25 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
import org.jetbrains.jet.lang.psi.JetFile; 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.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.actions.JetAddImportAction; import org.jetbrains.jet.plugin.actions.JetAddImportAction;
import org.jetbrains.jet.plugin.caches.JetCacheManager; import org.jetbrains.jet.plugin.caches.JetCacheManager;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/** /**
* Check possibility and perform fix for unresolved references. * Check possibility and perform fix for unresolved references.
* *
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public class ImportClassFix extends JetHintAction<JetSimpleNameExpression> implements HighPriorityAction { public class ImportClassAndFunFix extends JetHintAction<JetSimpleNameExpression> implements HighPriorityAction {
@NotNull @NotNull
private final List<String> suggestions; private final List<String> suggestions;
public ImportClassFix(@NotNull JetSimpleNameExpression element) { public ImportClassAndFunFix(@NotNull JetSimpleNameExpression element) {
super(element); super(element);
suggestions = computeSuggestions(element); suggestions = computeSuggestions(element);
} }
@@ -54,7 +53,39 @@ public class ImportClassFix extends JetHintAction<JetSimpleNameExpression> imple
return Collections.emptyList(); return Collections.emptyList();
} }
return getClassNames(element, file.getProject()); final ArrayList<String> result = new ArrayList<String>();
result.addAll(getClassNames(element, file.getProject()));
result.addAll(getJetTopLevelFunctions(element, file.getProject()));
return result;
}
private static Collection<String> getJetTopLevelFunctions(@NotNull JetSimpleNameExpression expression, @NotNull Project project) {
final String referenceName = expression.getReferencedName();
if (referenceName == null) {
return Collections.emptyList();
}
final Collection<JetNamedFunction> namedFunctions =
JetCacheManager.getInstance(project).getNamesCache().getTopLevelFunctionsByName(
referenceName, GlobalSearchScope.allScope(project));
final Collection<String> nullableNames =
Collections2.transform(Lists.newArrayList(namedFunctions), new Function<JetNamedFunction, String>() {
@Nullable
@Override
public String apply(@Nullable JetNamedFunction jetFunction) {
return jetFunction != null ? jetFunction.getQualifiedName() : null;
}
});
return Collections2.filter(nullableNames, new Predicate<String>() {
@Override
public boolean apply(@Nullable String fqn) {
return fqn != null && !fqn.isEmpty();
}
});
} }
/* /*
@@ -79,7 +110,7 @@ public class ImportClassFix extends JetHintAction<JetSimpleNameExpression> imple
private static Collection<String> getJavaClasses(@NotNull final String typeName, @NotNull Project project, final GlobalSearchScope scope) { private static Collection<String> getJavaClasses(@NotNull final String typeName, @NotNull Project project, final GlobalSearchScope scope) {
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project);
PsiClass[] classes = cache.getClassesByName(typeName, new DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { PsiClass[] classes = cache.getClassesByName(typeName, new DelegatingGlobalSearchScope(scope) {
@Override @Override
public boolean contains(@NotNull VirtualFile file) { public boolean contains(@NotNull VirtualFile file) {
return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE; return myBaseScope.contains(file) && file.getFileType() != JetFileType.INSTANCE;
@@ -166,7 +197,7 @@ public class ImportClassFix extends JetHintAction<JetSimpleNameExpression> imple
// There could be different psi elements (i.e. JetArrayAccessExpression), but we can fix only JetSimpleNameExpression case // There could be different psi elements (i.e. JetArrayAccessExpression), but we can fix only JetSimpleNameExpression case
if (diagnostic.getPsiElement() instanceof JetSimpleNameExpression) { if (diagnostic.getPsiElement() instanceof JetSimpleNameExpression) {
JetSimpleNameExpression psiElement = (JetSimpleNameExpression) diagnostic.getPsiElement(); JetSimpleNameExpression psiElement = (JetSimpleNameExpression) diagnostic.getPsiElement();
return new ImportClassFix(psiElement); return new ImportClassAndFunFix(psiElement);
} }
return null; return null;
@@ -108,7 +108,7 @@ public class QuickFixes {
add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory); add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory); add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
JetIntentionActionFactory<JetSimpleNameExpression> unresolvedReferenceFactory = ImportClassFix.createFactory(); JetIntentionActionFactory<JetSimpleNameExpression> unresolvedReferenceFactory = ImportClassAndFunFix.createFactory();
add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory); add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory);
add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory()); add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory());
@@ -20,7 +20,7 @@ import java.util.List;
/** /**
* @author yole * @author yole
*/ */
class JetSimpleNameReference extends JetPsiReference { public class JetSimpleNameReference extends JetPsiReference {
private final JetSimpleNameExpression myExpression; private final JetSimpleNameExpression myExpression;
@@ -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<JetNamedFunction> {
private static final JetExtensionFunctionNameIndex instance = new JetExtensionFunctionNameIndex();
public static JetExtensionFunctionNameIndex getInstance() {
return instance;
}
@Override
public StubIndexKey<String, JetNamedFunction> getKey() {
return JetIndexKeys.EXTENSION_FUNCTION_SHORT_NAME_KEY;
}
}
@@ -2,7 +2,7 @@ package org.jetbrains.jet.plugin.stubindex;
import com.intellij.psi.stubs.StubIndexKey; import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
@@ -10,11 +10,11 @@ import org.jetbrains.jet.lang.psi.JetFunction;
public interface JetIndexKeys { public interface JetIndexKeys {
StubIndexKey<String, JetClassOrObject> SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.class.shortName"); StubIndexKey<String, JetClassOrObject> SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.class.shortName");
StubIndexKey<String, JetClassOrObject> FQN_KEY = StubIndexKey.createIndexKey("jet.fqn"); StubIndexKey<String, JetClassOrObject> FQN_KEY = StubIndexKey.createIndexKey("jet.fqn");
StubIndexKey<String, JetFunction> TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name");
// StubIndexKey<String, JetFunction> TOP_LEVEL_FUNCTION_FQN_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name");
// StubIndexKey<String, JetObjectDeclaration> PACKAGE_OBJECT_KEY = StubIndexKey.createIndexKey("jet.package.object.fqn"); StubIndexKey<String, JetNamedFunction> TOP_LEVEL_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.short.name");
// StubIndexKey<String, JetFunction> EXTENSION_FUNCTION_TO_TYPE_FQN = StubIndexKey.createIndexKey("jet.extension.function.to.type.fqn"); StubIndexKey<String, JetNamedFunction> TOP_LEVEL_FUNCTION_FQNAME_KEY = StubIndexKey.createIndexKey("jet.top.level.function.fqname");
StubIndexKey<String, JetNamedFunction> EXTENSION_FUNCTION_SHORT_NAME_KEY = StubIndexKey.createIndexKey("jet.top.level.extension.function.short.name");
StubIndexKey<String, JetNamedFunction> EXTENSION_FUNCTION_FQNAME_KEY = StubIndexKey.createIndexKey("jet.top.level.extension.function.fqname");
} }
@@ -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);
}
}
};
}
}
@@ -5,27 +5,27 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension; import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndexKey; import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction;
import java.util.Collection; import java.util.Collection;
/** /**
* @author Nikolay Krasko * @author Nikolay Krasko
*/ */
public class JetShortFunctionNameIndex extends StringStubIndexExtension<JetFunction> { public class JetShortFunctionNameIndex extends StringStubIndexExtension<JetNamedFunction> {
private static final JetShortClassNameIndex ourInstance = new JetShortClassNameIndex(); private static final JetShortFunctionNameIndex ourInstance = new JetShortFunctionNameIndex();
public static JetShortClassNameIndex getInstance() { public static JetShortFunctionNameIndex getInstance() {
return ourInstance; return ourInstance;
} }
@Override @Override
public StubIndexKey<String, JetFunction> getKey() { public StubIndexKey<String, JetNamedFunction> getKey() {
return JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY; return JetIndexKeys.TOP_LEVEL_FUNCTION_SHORT_NAME_KEY;
} }
@Override @Override
public Collection<JetFunction> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) { public Collection<JetNamedFunction> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
return super.get(s, project, new JetSourceFilterScope(scope)); return super.get(s, project, new JetSourceFilterScope(scope));
} }
} }
@@ -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);
}
}
}
}
@@ -1,3 +1,5 @@
package some;
open class MyClass() { open class MyClass() {
} }
@@ -0,0 +1,8 @@
// "Import Class" "true"
package functionimporttest
import functionimporttest.data.someTestFun
fun functionImportTest() {
someTestFun()
}
@@ -0,0 +1,7 @@
package functionimporttest.data
fun String.someTestFun() {
}
fun someTestFun() {
}
@@ -0,0 +1,6 @@
// "Import Class" "true"
package functionimporttest
fun functionImportTest() {
<caret>someTestFun()
}
@@ -26,11 +26,8 @@ public class FunctionsHandlerTest extends LightCompletionTestCase {
checkResultByFile("SingleBrackets.kt.after"); checkResultByFile("SingleBrackets.kt.after");
} }
// public void
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + File.separator;
File.separator;
} }
} }