Name validator for introduce variable action.
This commit is contained in:
@@ -68,32 +68,34 @@ public final class TipsManager {
|
||||
excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors()),
|
||||
resolutionScope, new ExpressionReceiver(receiverExpression, expressionType));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
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 getVariantsNoReceiver(expression, context);
|
||||
}
|
||||
|
||||
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(
|
||||
@NotNull Collection<DeclarationDescriptor> descriptors) {
|
||||
|
||||
@@ -17,8 +17,22 @@
|
||||
package org.jetbrains.jet.plugin.refactoring;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
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
|
||||
@@ -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) {
|
||||
myPlace = place;
|
||||
public JetNameValidatorImpl(PsiElement container, PsiElement anchor) {
|
||||
myContainer = container;
|
||||
myAnchor = anchor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
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() {
|
||||
return myPlace.getProject();
|
||||
return myContainer.getProject();
|
||||
}
|
||||
}
|
||||
|
||||
+32
-21
@@ -128,11 +128,15 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
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 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 ArrayList<JetExpression> references = new ArrayList<JetExpression>();
|
||||
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
||||
@@ -192,23 +196,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
||||
} else variableText += expression.getText();
|
||||
JetProperty property = JetPsiFactory.createProperty(project, variableText);
|
||||
if (property == null) return;
|
||||
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;
|
||||
}
|
||||
PsiElement anchor = calculateAnchor(commonParent, commonContainer, allReplaces);
|
||||
if (anchor == null) return;
|
||||
boolean needBraces = !(commonContainer instanceof JetBlockExpression ||
|
||||
commonContainer instanceof JetClassBody ||
|
||||
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) {
|
||||
if (expression instanceof JetParenthesizedExpression) {
|
||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression) expression;
|
||||
|
||||
Reference in New Issue
Block a user