Implemented compacting type names and adding valid imports in override/implements handler.
#KT-1602 fixed
This commit is contained in:
@@ -61,6 +61,7 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice();
|
||||||
|
|
||||||
/** A scope where type of expression has been resolved */
|
/** A scope where type of expression has been resolved */
|
||||||
|
WritableSlice<JetTypeReference, JetScope> TYPE_RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||||
|
|
||||||
/** Collected during analyze, used in IDE in auto-cast completion */
|
/** Collected during analyze, used in IDE in auto-cast completion */
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ public class TypeResolver {
|
|||||||
JetTypeElement typeElement = typeReference.getTypeElement();
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
JetType type = resolveTypeElement(scope, annotations, typeElement, false, trace, checkBounds);
|
JetType type = resolveTypeElement(scope, annotations, typeElement, false, trace, checkBounds);
|
||||||
trace.record(BindingContext.TYPE, typeReference, type);
|
trace.record(BindingContext.TYPE, typeReference, type);
|
||||||
|
trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, scope);
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -472,6 +472,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
|
context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result);
|
||||||
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
|
context.trace.record(BindingContext.REFERENCE_TARGET, expression.getInstanceReference(), result.getConstructor().getDeclarationDescriptor());
|
||||||
|
if (superTypeQualifier != null) {
|
||||||
|
context.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, superTypeQualifier, context.scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, context);
|
return DataFlowUtils.checkType(result, expression, context);
|
||||||
|
|||||||
+85
-15
@@ -33,6 +33,8 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
@@ -81,11 +83,80 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetElement element : generateOverridingMembers(selectedElements, (JetFile)classOrObject.getContainingFile(), false)) {
|
List<JetElement> elementsToCompact = new ArrayList<JetElement>();
|
||||||
afterAnchor = body.addAfter(element, afterAnchor);
|
final JetFile file = (JetFile)classOrObject.getContainingFile();
|
||||||
|
for (JetElement element : generateOverridingMembers(selectedElements, file)) {
|
||||||
|
PsiElement added = body.addAfter(element, afterAnchor);
|
||||||
|
afterAnchor = added;
|
||||||
|
elementsToCompact.add((JetElement)added);
|
||||||
|
}
|
||||||
|
compactReferenceToClasses(elementsToCompact);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compactReferenceToClasses(List<JetElement> elementsToCompact) {
|
||||||
|
if (elementsToCompact.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final JetFile file = (JetFile) elementsToCompact.get(0).getContainingFile();
|
||||||
|
final BindingContext bc = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file).getBindingContext();
|
||||||
|
for (JetElement element : elementsToCompact) {
|
||||||
|
element.accept(new JetVisitorVoid() {
|
||||||
|
@Override
|
||||||
|
public void visitJetElement(JetElement element) {
|
||||||
|
element.acceptChildren(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTypeReference(JetTypeReference typeReference) {
|
||||||
|
super.visitTypeReference(typeReference);
|
||||||
|
|
||||||
|
JetTypeElement typeElement = typeReference.getTypeElement();
|
||||||
|
if (typeElement instanceof JetNullableType) {
|
||||||
|
typeElement = ((JetNullableType) typeElement).getInnerType();
|
||||||
|
}
|
||||||
|
if (typeElement instanceof JetUserType) {
|
||||||
|
JetUserType userType = (JetUserType) typeElement;
|
||||||
|
DeclarationDescriptor target = bc.get(BindingContext.REFERENCE_TARGET,
|
||||||
|
userType.getReferenceExpression());
|
||||||
|
if (target instanceof ClassDescriptor) {
|
||||||
|
ClassDescriptor targetClass = (ClassDescriptor) target;
|
||||||
|
ClassDescriptor targetTopLevelClass = ImportInsertHelper.getTopLevelClass(targetClass);
|
||||||
|
|
||||||
|
JetScope scope = bc.get(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference);
|
||||||
|
ClassifierDescriptor classifier = scope.getClassifier(targetTopLevelClass.getName());
|
||||||
|
if (targetTopLevelClass == classifier) {
|
||||||
|
compactReferenceToClass(userType, targetClass);
|
||||||
|
}
|
||||||
|
else if (classifier == null) {
|
||||||
|
ImportInsertHelper.addImportDirective(DescriptorUtils.getFQName(targetTopLevelClass).toSafe(), file);
|
||||||
|
compactReferenceToClass(userType, targetClass);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// leave FQ name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void compactReferenceToClass(JetUserType userType, ClassDescriptor targetClass) {
|
||||||
|
if (targetClass == JetStandardClasses.getUnitType().getConstructor().getDeclarationDescriptor()) {
|
||||||
|
// do not replace "Unit" with "Tuple0"
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String name = targetClass.getName();
|
||||||
|
DeclarationDescriptor parent = targetClass.getContainingDeclaration();
|
||||||
|
while (parent instanceof ClassDescriptor) {
|
||||||
|
name = parent.getName() + "." + name;
|
||||||
|
parent = parent.getContainingDeclaration();
|
||||||
|
}
|
||||||
|
JetTypeArgumentList typeArgumentList = userType.getTypeArgumentList();
|
||||||
|
userType.replace(JetPsiFactory.createType(userType.getProject(), name + (typeArgumentList == null ? "" : typeArgumentList.getText())));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static PsiElement findInsertAfterAnchor(Editor editor, final JetClassBody body) {
|
private static PsiElement findInsertAfterAnchor(Editor editor, final JetClassBody body) {
|
||||||
PsiElement afterAnchor = body.getLBrace();
|
PsiElement afterAnchor = body.getLBrace();
|
||||||
@@ -109,21 +180,21 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
return afterAnchor;
|
return afterAnchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<JetElement> generateOverridingMembers(List<DescriptorClassMember> selectedElements, JetFile file, boolean fqNames) {
|
private static List<JetElement> generateOverridingMembers(List<DescriptorClassMember> selectedElements, JetFile file) {
|
||||||
List<JetElement> overridingMembers = new ArrayList<JetElement>();
|
List<JetElement> overridingMembers = new ArrayList<JetElement>();
|
||||||
for (DescriptorClassMember selectedElement : selectedElements) {
|
for (DescriptorClassMember selectedElement : selectedElements) {
|
||||||
final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
|
||||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||||
overridingMembers.add(overrideFunction(file.getProject(), file, (SimpleFunctionDescriptor)descriptor, fqNames));
|
overridingMembers.add(overrideFunction(file.getProject(), (SimpleFunctionDescriptor)descriptor));
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof PropertyDescriptor) {
|
else if (descriptor instanceof PropertyDescriptor) {
|
||||||
overridingMembers.add(overrideProperty(file.getProject(), file, (PropertyDescriptor)descriptor, fqNames));
|
overridingMembers.add(overrideProperty(file.getProject(), (PropertyDescriptor)descriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return overridingMembers;
|
return overridingMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JetElement overrideProperty(Project project, JetFile file, PropertyDescriptor descriptor, boolean fqNames) {
|
private static JetElement overrideProperty(Project project, PropertyDescriptor descriptor) {
|
||||||
StringBuilder bodyBuilder = new StringBuilder();
|
StringBuilder bodyBuilder = new StringBuilder();
|
||||||
bodyBuilder.append(displayableVisibility(descriptor)).append("override ");
|
bodyBuilder.append(displayableVisibility(descriptor)).append("override ");
|
||||||
if (descriptor.isVar()) {
|
if (descriptor.isVar()) {
|
||||||
@@ -134,7 +205,6 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
}
|
}
|
||||||
bodyBuilder.append(descriptor.getName()).append(" : ").append(DescriptorRenderer.COMPACT.renderTypeWithShortNames(
|
bodyBuilder.append(descriptor.getName()).append(" : ").append(DescriptorRenderer.COMPACT.renderTypeWithShortNames(
|
||||||
descriptor.getType()));
|
descriptor.getType()));
|
||||||
ImportInsertHelper.addImportDirectivesIfNeeded(descriptor.getType(), file);
|
|
||||||
String initializer = defaultInitializer(descriptor.getType(), JetStandardLibrary.getInstance());
|
String initializer = defaultInitializer(descriptor.getType(), JetStandardLibrary.getInstance());
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
bodyBuilder.append(" = ").append(initializer);
|
bodyBuilder.append(" = ").append(initializer);
|
||||||
@@ -145,7 +215,11 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
return JetPsiFactory.createProperty(project, bodyBuilder.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JetElement overrideFunction(Project project, JetFile file, SimpleFunctionDescriptor descriptor, boolean fqNames) {
|
private static String renderType(JetType type) {
|
||||||
|
return DescriptorRenderer.TEXT.renderType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JetElement overrideFunction(Project project, SimpleFunctionDescriptor descriptor) {
|
||||||
StringBuilder bodyBuilder = new StringBuilder();
|
StringBuilder bodyBuilder = new StringBuilder();
|
||||||
bodyBuilder.append(displayableVisibility(descriptor));
|
bodyBuilder.append(displayableVisibility(descriptor));
|
||||||
bodyBuilder.append("override fun ");
|
bodyBuilder.append("override fun ");
|
||||||
@@ -164,7 +238,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
if (!upperBounds.isEmpty()) {
|
if (!upperBounds.isEmpty()) {
|
||||||
boolean firstUpperBound = true;
|
boolean firstUpperBound = true;
|
||||||
for (JetType upperBound : upperBounds) {
|
for (JetType upperBound : upperBounds) {
|
||||||
String upperBoundText = " : " + DescriptorRenderer.TEXT.renderTypeWithShortNames(upperBound);
|
String upperBoundText = " : " + renderType(upperBound);
|
||||||
if (upperBound != JetStandardClasses.getDefaultBound()) {
|
if (upperBound != JetStandardClasses.getDefaultBound()) {
|
||||||
if (firstUpperBound) {
|
if (firstUpperBound) {
|
||||||
bodyBuilder.append(upperBoundText);
|
bodyBuilder.append(upperBoundText);
|
||||||
@@ -172,7 +246,6 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
whereRestrictions.add(param.getName() + upperBoundText);
|
whereRestrictions.add(param.getName() + upperBoundText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportInsertHelper.addImportDirectivesIfNeeded(upperBound, file);
|
|
||||||
firstUpperBound = false;
|
firstUpperBound = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,9 +275,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
first = false;
|
first = false;
|
||||||
bodyBuilder.append(parameterDescriptor.getName());
|
bodyBuilder.append(parameterDescriptor.getName());
|
||||||
bodyBuilder.append(" : ");
|
bodyBuilder.append(" : ");
|
||||||
bodyBuilder.append(DescriptorRenderer.TEXT.renderTypeWithShortNames(parameterDescriptor.getType()));
|
bodyBuilder.append(renderType(parameterDescriptor.getType()));
|
||||||
|
|
||||||
ImportInsertHelper.addImportDirectivesIfNeeded(parameterDescriptor.getType(), file);
|
|
||||||
|
|
||||||
if (!isAbstractFun) {
|
if (!isAbstractFun) {
|
||||||
delegationBuilder.append(parameterDescriptor.getName());
|
delegationBuilder.append(parameterDescriptor.getName());
|
||||||
@@ -219,8 +290,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
|
|||||||
|
|
||||||
boolean returnsNotUnit = returnType != null && !stdlib.getTuple0Type().equals(returnType);
|
boolean returnsNotUnit = returnType != null && !stdlib.getTuple0Type().equals(returnType);
|
||||||
if (returnsNotUnit) {
|
if (returnsNotUnit) {
|
||||||
bodyBuilder.append(" : ").append(DescriptorRenderer.TEXT.renderTypeWithShortNames(returnType));
|
bodyBuilder.append(" : ").append(renderType(returnType));
|
||||||
ImportInsertHelper.addImportDirectivesIfNeeded(returnType, file);
|
|
||||||
}
|
}
|
||||||
if (!whereRestrictions.isEmpty()) {
|
if (!whereRestrictions.isEmpty()) {
|
||||||
bodyBuilder.append("\n").append("where ").append(StringUtil.join(whereRestrictions, ", "));
|
bodyBuilder.append("\n").append("where ").append(StringUtil.join(whereRestrictions, ", "));
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ public class ImportInsertHelper {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClassDescriptor getTopLevelClass(ClassDescriptor classDescriptor) {
|
public static ClassDescriptor getTopLevelClass(ClassDescriptor classDescriptor) {
|
||||||
while (true) {
|
while (true) {
|
||||||
DeclarationDescriptor parent = classDescriptor.getContainingDeclaration();
|
DeclarationDescriptor parent = classDescriptor.getContainingDeclaration();
|
||||||
if (parent instanceof ClassDescriptor) {
|
if (parent instanceof ClassDescriptor) {
|
||||||
|
|||||||
Reference in New Issue
Block a user