Name validator for introduce variable action.
This commit is contained in:
@@ -68,32 +68,34 @@ public final class TipsManager {
|
|||||||
excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors()),
|
excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors()),
|
||||||
resolutionScope, new ExpressionReceiver(receiverExpression, expressionType));
|
resolutionScope, new ExpressionReceiver(receiverExpression, expressionType));
|
||||||
}
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
return getVariantsNoReceiver(expression, context);
|
||||||
if (resolutionScope != null) {
|
|
||||||
if (expression.getParent() instanceof JetImportDirective || expression.getParent() instanceof JetNamespaceHeader) {
|
|
||||||
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors());
|
|
||||||
} else {
|
|
||||||
HashSet<DeclarationDescriptor> descriptorsSet = Sets.newHashSet();
|
|
||||||
|
|
||||||
ArrayList<ReceiverDescriptor> result = new ArrayList<ReceiverDescriptor>();
|
|
||||||
resolutionScope.getImplicitReceiversHierarchy(result);
|
|
||||||
|
|
||||||
for (ReceiverDescriptor receiverDescriptor : result) {
|
|
||||||
JetType receiverType = receiverDescriptor.getType();
|
|
||||||
descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors());
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptorsSet.addAll(resolutionScope.getAllDescriptors());
|
|
||||||
return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Collection<DeclarationDescriptor> getVariantsNoReceiver(JetExpression expression, BindingContext context) {
|
||||||
|
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
|
||||||
|
if (resolutionScope != null) {
|
||||||
|
if (expression.getParent() instanceof JetImportDirective || expression.getParent() instanceof JetNamespaceHeader) {
|
||||||
|
return excludeNonPackageDescriptors(resolutionScope.getAllDescriptors());
|
||||||
|
} else {
|
||||||
|
HashSet<DeclarationDescriptor> descriptorsSet = Sets.newHashSet();
|
||||||
|
|
||||||
|
ArrayList<ReceiverDescriptor> result = new ArrayList<ReceiverDescriptor>();
|
||||||
|
resolutionScope.getImplicitReceiversHierarchy(result);
|
||||||
|
|
||||||
|
for (ReceiverDescriptor receiverDescriptor : result) {
|
||||||
|
JetType receiverType = receiverDescriptor.getType();
|
||||||
|
descriptorsSet.addAll(receiverType.getMemberScope().getAllDescriptors());
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptorsSet.addAll(resolutionScope.getAllDescriptors());
|
||||||
|
return excludeNotCallableExtensions(excludePrivateDescriptors(descriptorsSet), resolutionScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
public static Collection<DeclarationDescriptor> excludePrivateDescriptors(
|
public static Collection<DeclarationDescriptor> excludePrivateDescriptors(
|
||||||
@NotNull Collection<DeclarationDescriptor> descriptors) {
|
@NotNull Collection<DeclarationDescriptor> descriptors) {
|
||||||
|
|||||||
@@ -17,8 +17,22 @@
|
|||||||
package org.jetbrains.jet.plugin.refactoring;
|
package org.jetbrains.jet.plugin.refactoring;
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.Ref;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.compiler.TipsManager;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetVisitorVoid;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Alefas
|
* User: Alefas
|
||||||
@@ -39,18 +53,76 @@ public class JetNameValidatorImpl implements JetNameValidator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PsiElement myPlace;
|
private final PsiElement myContainer;
|
||||||
|
private PsiElement myAnchor;
|
||||||
|
BindingContext myBindingContext;
|
||||||
|
|
||||||
public JetNameValidatorImpl(PsiElement place) {
|
public JetNameValidatorImpl(PsiElement container, PsiElement anchor) {
|
||||||
myPlace = place;
|
myContainer = container;
|
||||||
|
myAnchor = anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String validateName(String name) {
|
public String validateName(String name) {
|
||||||
return name;
|
if (validateInner(name)) return name;
|
||||||
|
int i = 1;
|
||||||
|
while (true) {
|
||||||
|
if (validateInner(name + i)) return name + i;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validateInner(String name) {
|
||||||
|
PsiElement sibling;
|
||||||
|
if (myAnchor != null) {
|
||||||
|
sibling = myAnchor;
|
||||||
|
} else {
|
||||||
|
if (myContainer instanceof JetExpression) {
|
||||||
|
return checkElement(name, myContainer);
|
||||||
|
}
|
||||||
|
sibling = myContainer.getFirstChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (sibling != null) {
|
||||||
|
if (!checkElement(name, sibling)) return false;
|
||||||
|
sibling = sibling.getNextSibling();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkElement(final String name, PsiElement sibling) {
|
||||||
|
if (myBindingContext == null) {
|
||||||
|
myBindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(
|
||||||
|
(JetFile) myContainer.getContainingFile());
|
||||||
|
}
|
||||||
|
final Ref<Boolean> result = new Ref<Boolean>(true);
|
||||||
|
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||||
|
@Override
|
||||||
|
public void visitElement(PsiElement element) {
|
||||||
|
if (result.get()) {
|
||||||
|
element.acceptChildren(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitExpression(JetExpression expression) {
|
||||||
|
Collection<DeclarationDescriptor> variants =
|
||||||
|
TipsManager.getVariantsNoReceiver(expression, myBindingContext);
|
||||||
|
for (DeclarationDescriptor variant : variants) {
|
||||||
|
if (variant.getName().equals(name)) {
|
||||||
|
result.set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.visitExpression(expression);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sibling.accept(visitor);
|
||||||
|
return result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Project getProject() {
|
public Project getProject() {
|
||||||
return myPlace.getProject();
|
return myContainer.getProject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-21
@@ -128,11 +128,15 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
allReplaces = Collections.singletonList(expression);
|
allReplaces = Collections.singletonList(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] suggestedNames = JetNameSuggester.suggestNames(expression, new JetNameValidatorImpl(expression));
|
|
||||||
final LinkedHashSet<String> suggestedNamesSet = new LinkedHashSet<String>();
|
|
||||||
Collections.addAll(suggestedNamesSet, suggestedNames);
|
|
||||||
PsiElement commonParent = PsiTreeUtil.findCommonParent(allReplaces);
|
PsiElement commonParent = PsiTreeUtil.findCommonParent(allReplaces);
|
||||||
PsiElement commonContainer = getContainer(commonParent);
|
PsiElement commonContainer = getContainer(commonParent);
|
||||||
|
JetNameValidatorImpl validator = new JetNameValidatorImpl(commonContainer,
|
||||||
|
calculateAnchor(commonParent,
|
||||||
|
commonContainer,
|
||||||
|
allReplaces));
|
||||||
|
String[] suggestedNames = JetNameSuggester.suggestNames(expression, validator);
|
||||||
|
final LinkedHashSet<String> suggestedNamesSet = new LinkedHashSet<String>();
|
||||||
|
Collections.addAll(suggestedNamesSet, suggestedNames);
|
||||||
final Ref<JetProperty> propertyRef = new Ref<JetProperty>();
|
final Ref<JetProperty> propertyRef = new Ref<JetProperty>();
|
||||||
final ArrayList<JetExpression> references = new ArrayList<JetExpression>();
|
final ArrayList<JetExpression> references = new ArrayList<JetExpression>();
|
||||||
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
||||||
@@ -192,23 +196,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
} else variableText += expression.getText();
|
} else variableText += expression.getText();
|
||||||
JetProperty property = JetPsiFactory.createProperty(project, variableText);
|
JetProperty property = JetPsiFactory.createProperty(project, variableText);
|
||||||
if (property == null) return;
|
if (property == null) return;
|
||||||
PsiElement anchor = commonParent;
|
PsiElement anchor = calculateAnchor(commonParent, commonContainer, allReplaces);
|
||||||
if (anchor != commonContainer) {
|
if (anchor == null) return;
|
||||||
while (anchor.getParent() != commonContainer) {
|
|
||||||
anchor = anchor.getParent();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
anchor = commonContainer.getFirstChild();
|
|
||||||
int startOffset = commonContainer.getTextRange().getEndOffset();
|
|
||||||
for (JetExpression expr : allReplaces) {
|
|
||||||
int offset = expr.getTextRange().getStartOffset();
|
|
||||||
if (offset < startOffset) startOffset = offset;
|
|
||||||
}
|
|
||||||
while (anchor != null && !anchor.getTextRange().contains(startOffset)) {
|
|
||||||
anchor = anchor.getNextSibling();
|
|
||||||
}
|
|
||||||
if (anchor == null) return;
|
|
||||||
}
|
|
||||||
boolean needBraces = !(commonContainer instanceof JetBlockExpression ||
|
boolean needBraces = !(commonContainer instanceof JetBlockExpression ||
|
||||||
commonContainer instanceof JetClassBody ||
|
commonContainer instanceof JetClassBody ||
|
||||||
commonContainer instanceof JetClassInitializer);
|
commonContainer instanceof JetClassInitializer);
|
||||||
@@ -263,7 +252,29 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PsiElement calculateAnchor(PsiElement commonParent, PsiElement commonContainer,
|
||||||
|
List<JetExpression> allReplaces) {
|
||||||
|
PsiElement anchor = commonParent;
|
||||||
|
if (anchor != commonContainer) {
|
||||||
|
while (anchor.getParent() != commonContainer) {
|
||||||
|
anchor = anchor.getParent();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
anchor = commonContainer.getFirstChild();
|
||||||
|
int startOffset = commonContainer.getTextRange().getEndOffset();
|
||||||
|
for (JetExpression expr : allReplaces) {
|
||||||
|
int offset = expr.getTextRange().getStartOffset();
|
||||||
|
if (offset < startOffset) startOffset = offset;
|
||||||
|
}
|
||||||
|
while (anchor != null && !anchor.getTextRange().contains(startOffset)) {
|
||||||
|
anchor = anchor.getNextSibling();
|
||||||
|
}
|
||||||
|
if (anchor == null) return null;
|
||||||
|
}
|
||||||
|
return anchor;
|
||||||
|
}
|
||||||
|
|
||||||
private static ArrayList<JetExpression> findOccurrences(PsiElement occurrenceContainer, @NotNull JetExpression expression) {
|
private static ArrayList<JetExpression> findOccurrences(PsiElement occurrenceContainer, @NotNull JetExpression expression) {
|
||||||
if (expression instanceof JetParenthesizedExpression) {
|
if (expression instanceof JetParenthesizedExpression) {
|
||||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression;
|
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression;
|
||||||
|
|||||||
Reference in New Issue
Block a user