Merge branch 'master' of git+ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -1,41 +0,0 @@
|
|||||||
package org.jetbrains.jet.lang.descriptors;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.jet.util.QualifiedNamesUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Nikolay Krasko
|
|
||||||
*/
|
|
||||||
public final class DescriptorsUtils {
|
|
||||||
|
|
||||||
private DescriptorsUtils() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFQName(@NotNull NamespaceDescriptor namespaceDescriptor) {
|
|
||||||
|
|
||||||
NamespaceDescriptor tempNamespace = namespaceDescriptor;
|
|
||||||
String fqn = tempNamespace.getName();
|
|
||||||
|
|
||||||
while (tempNamespace.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
|
||||||
tempNamespace = (NamespaceDescriptor) tempNamespace.getContainingDeclaration();
|
|
||||||
|
|
||||||
assert tempNamespace != null;
|
|
||||||
fqn = tempNamespace.getName() + "." + fqn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fqn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getFQName(@NotNull NamedFunctionDescriptor functionDescriptor) {
|
|
||||||
if (functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
|
|
||||||
final String namespaceFQN = getFQName((NamespaceDescriptor) functionDescriptor.getContainingDeclaration());
|
|
||||||
return QualifiedNamesUtil.combine(namespaceFQN, functionDescriptor.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Currently supported only for top level functions");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isTopLevelFunction(@NotNull NamedFunctionDescriptor functionDescriptor) {
|
|
||||||
return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -138,6 +138,17 @@ public class JetPsiUtil {
|
|||||||
return jetClass.getName();
|
return jetClass.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable @JetElement.IfNotParsed
|
||||||
|
public static String getImportPath(JetImportDirective importDirective) {
|
||||||
|
final JetExpression importedReference = importDirective.getImportedReference();
|
||||||
|
if (importedReference == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String text = importedReference.getText();
|
||||||
|
return text.replaceAll(" ", "") + (importDirective.isAllUnder() ? ".*" : "");
|
||||||
|
}
|
||||||
|
|
||||||
private static String makeFQName(String prefix, JetClassOrObject jetClass) {
|
private static String makeFQName(String prefix, JetClassOrObject jetClass) {
|
||||||
return ((prefix == null || prefix.length() == 0) ? "" : prefix + ".") + jetClass.getName();
|
return ((prefix == null || prefix.length() == 0) ? "" : prefix + ".") + jetClass.getName();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,16 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
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.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.intellij.psi.PsiElement;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetObjectDeclaration;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetObjectDeclarationName;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
|
||||||
@@ -175,6 +168,10 @@ public class DescriptorUtils {
|
|||||||
return descriptor.getName();
|
return descriptor.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isTopLevelFunction(@NotNull NamedFunctionDescriptor functionDescriptor) {
|
||||||
|
return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static <D extends DeclarationDescriptor> D getParentOfType(@Nullable DeclarationDescriptor descriptor, @NotNull Class<D> aClass) {
|
public static <D extends DeclarationDescriptor> D getParentOfType(@Nullable DeclarationDescriptor descriptor, @NotNull Class<D> aClass) {
|
||||||
return getParentOfType(descriptor, aClass, true);
|
return getParentOfType(descriptor, aClass, true);
|
||||||
|
|||||||
@@ -100,4 +100,19 @@ public final class QualifiedNamesUtil {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that given fqn could be imported with import.
|
||||||
|
*
|
||||||
|
* @param importPath path from the import. Could contain .* part
|
||||||
|
* @param fqn
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isImported(@NotNull String importPath, @NotNull String fqn) {
|
||||||
|
if (importPath.endsWith("*")) {
|
||||||
|
return withoutLastSegment(importPath).equals(withoutLastSegment(fqn));
|
||||||
|
}
|
||||||
|
|
||||||
|
return importPath.equals(fqn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+40
-12
@@ -4,14 +4,18 @@ import com.intellij.codeInsight.AutoPopupController;
|
|||||||
import com.intellij.codeInsight.completion.InsertHandler;
|
import com.intellij.codeInsight.completion.InsertHandler;
|
||||||
import com.intellij.codeInsight.completion.InsertionContext;
|
import com.intellij.codeInsight.completion.InsertionContext;
|
||||||
import com.intellij.codeInsight.lookup.LookupElement;
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.editor.Document;
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.psi.PsiDocumentManager;
|
import com.intellij.psi.PsiDocumentManager;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DescriptorsUtils;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.plugin.completion.JetLookupObject;
|
import org.jetbrains.jet.plugin.completion.JetLookupObject;
|
||||||
import org.jetbrains.jet.plugin.quickfix.ImportClassHelper;
|
import org.jetbrains.jet.plugin.quickfix.ImportClassHelper;
|
||||||
|
|
||||||
@@ -38,7 +42,10 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
|
|||||||
|
|
||||||
int startOffset = context.getStartOffset();
|
int startOffset = context.getStartOffset();
|
||||||
PsiElement element = context.getFile().findElementAt(startOffset);
|
PsiElement element = context.getFile().findElementAt(startOffset);
|
||||||
if (element == null) return;
|
if (element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int lookupStringLength = item.getLookupString().length();
|
int lookupStringLength = item.getLookupString().length();
|
||||||
int endOffset = startOffset + lookupStringLength;
|
int endOffset = startOffset + lookupStringLength;
|
||||||
Document document = context.getDocument();
|
Document document = context.getDocument();
|
||||||
@@ -63,22 +70,43 @@ public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
|
|||||||
|
|
||||||
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
|
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument());
|
||||||
|
|
||||||
// Should be done after all string insertions and document commitment.
|
|
||||||
addImport(context, item);
|
addImport(context, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addImport(InsertionContext context, LookupElement item) {
|
private static void addImport(final InsertionContext context, final @NotNull LookupElement item) {
|
||||||
if (context.getFile() instanceof JetFile && item.getObject() instanceof JetLookupObject) {
|
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||||
final DeclarationDescriptor descriptor = ((JetLookupObject) item.getObject()).getDescriptor();
|
@Override
|
||||||
if (descriptor instanceof NamedFunctionDescriptor) {
|
public void run() {
|
||||||
|
int startOffset = context.getStartOffset();
|
||||||
|
PsiElement element = context.getFile().findElementAt(startOffset);
|
||||||
|
if (element == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
JetFile file = (JetFile) context.getFile();
|
// No auto import for qualified expressions
|
||||||
NamedFunctionDescriptor functionDescriptor = (NamedFunctionDescriptor) descriptor;
|
if (PsiTreeUtil.getParentOfType(element, JetQualifiedExpression.class) != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (DescriptorsUtils.isTopLevelFunction(functionDescriptor)) {
|
if (context.getFile() instanceof JetFile && item.getObject() instanceof JetLookupObject) {
|
||||||
ImportClassHelper.addImportDirective(DescriptorsUtils.getFQName(functionDescriptor), file);
|
final DeclarationDescriptor descriptor = ((JetLookupObject) item.getObject()).getDescriptor();
|
||||||
|
if (descriptor instanceof NamedFunctionDescriptor) {
|
||||||
|
|
||||||
|
final JetFile file = (JetFile) context.getFile();
|
||||||
|
NamedFunctionDescriptor functionDescriptor = (NamedFunctionDescriptor) descriptor;
|
||||||
|
final String fqn = DescriptorUtils.getFQName(functionDescriptor);
|
||||||
|
|
||||||
|
if (DescriptorUtils.isTopLevelFunction(functionDescriptor)) {
|
||||||
|
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ImportClassHelper.addImportDirective(fqn, file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,10 +52,11 @@ public class ImportClassHelper {
|
|||||||
JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importString);
|
JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importString);
|
||||||
|
|
||||||
if (!importDirectives.isEmpty()) {
|
if (!importDirectives.isEmpty()) {
|
||||||
|
|
||||||
// Check if import is already present
|
// Check if import is already present
|
||||||
for (JetImportDirective directive : importDirectives) {
|
for (JetImportDirective directive : importDirectives) {
|
||||||
if (directive.getText().endsWith(importString) || directive.getText().endsWith(importString + ";")) {
|
String importPath = JetPsiUtil.getImportPath(directive);
|
||||||
|
if (importPath != null && QualifiedNamesUtil.isImported(importPath, importString)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting.*
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
data.topLevelFu<caret>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package jettesting.data
|
||||||
|
|
||||||
|
fun topLevelFunction() {
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting.*
|
||||||
|
|
||||||
|
fun other() {
|
||||||
|
data.topLevelFunction()
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting.data.*;
|
||||||
|
|
||||||
|
fun otherfun() {
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting.data.*;
|
||||||
|
|
||||||
|
fun otherfun() {
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting . data .*;
|
||||||
|
|
||||||
|
fun otherfun() {
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package some
|
||||||
|
|
||||||
|
import jettesting . data .*;
|
||||||
|
|
||||||
|
fun otherfun() {
|
||||||
|
}
|
||||||
@@ -14,6 +14,10 @@ public class CompletionMultifileHandlerTest extends CompletionTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testTopLevelFunctionInQualifiedExpr() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
public void doTest() {
|
public void doTest() {
|
||||||
String fileName = getTestName(false);
|
String fileName = getTestName(false);
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.jetbrains.jet.plugin.quickfix;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nikolay Krasko
|
||||||
|
*/
|
||||||
|
public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase {
|
||||||
|
public void testDoNotImportIfGeneralExist() {
|
||||||
|
configureByFile(getTestName(false) + ".kt");
|
||||||
|
ImportClassHelper.addImportDirective("jettesting.data.testFunction", (JetFile) getFile());
|
||||||
|
checkResultByFile(getTestName(false) + ".kt.after");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDoNotImportIfGeneralSpaceExist() {
|
||||||
|
configureByFile(getTestName(false) + ".kt");
|
||||||
|
ImportClassHelper.addImportDirective("jettesting.data.testFunction", (JetFile) getFile());
|
||||||
|
checkResultByFile(getTestName(false) + ".kt.after");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTestDataPath() {
|
||||||
|
return PluginTestCaseBase.getTestDataPathBase() + "/quickfix/importHelper/";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user