diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java index 664166ee9dc..e682f0fb862 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallableDeclaration.java @@ -27,4 +27,7 @@ public interface JetCallableDeclaration extends JetNamedDeclaration, JetTypePara @Nullable JetTypeReference getReturnTypeRef(); + + @Nullable + JetTypeReference setReturnTypeRef(@Nullable JetTypeReference typeRef); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionNotStubbed.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionNotStubbed.java index 48d16ddc054..64340f16ce7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionNotStubbed.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionNotStubbed.java @@ -22,6 +22,7 @@ import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lang.psi.typeRefHelpers.TypeRefHelpersPackage; import org.jetbrains.jet.lexer.JetTokens; import java.util.Collections; @@ -77,20 +78,13 @@ abstract public class JetFunctionNotStubbed extends JetTypeParameterListOwnerNot @Override @Nullable public JetTypeReference getReturnTypeRef() { - boolean colonPassed = false; - PsiElement child = getFirstChild(); - while (child != null) { - IElementType tt = child.getNode().getElementType(); - if (tt == JetTokens.COLON) { - colonPassed = true; - } - if (colonPassed && child instanceof JetTypeReference) { - return (JetTypeReference) child; - } - child = child.getNextSibling(); - } + return TypeRefHelpersPackage.getTypeRef(this); + } - return null; + @Nullable + @Override + public JetTypeReference setReturnTypeRef(@Nullable JetTypeReference typeRef) { + return TypeRefHelpersPackage.setTypeRef(this, getValueParameterList(), typeRef); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java index baf22fe5d15..9e4f01ac9dd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetMultiDeclarationEntry.java @@ -21,6 +21,7 @@ import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lang.psi.typeRefHelpers.TypeRefHelpersPackage; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lexer.JetTokens; @@ -34,7 +35,12 @@ public class JetMultiDeclarationEntry extends JetNamedDeclarationNotStubbed impl @Override public JetTypeReference getTypeRef() { - return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); + return TypeRefHelpersPackage.getTypeRef(this); + } + + @Nullable + public JetTypeReference setTypeRef(@Nullable JetTypeReference typeRef) { + return TypeRefHelpersPackage.setTypeRef(this, getNameIdentifier(), typeRef); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java index f3a94f0c1bd..74295023991 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java @@ -26,6 +26,7 @@ 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.elements.JetStubElementTypes; +import org.jetbrains.jet.lang.psi.typeRefHelpers.TypeRefHelpersPackage; import org.jetbrains.jet.lexer.JetTokens; import java.util.Collections; @@ -174,25 +175,13 @@ public class JetNamedFunction extends JetTypeParameterListOwnerStub { @@ -40,11 +41,17 @@ public class JetParameter extends JetNamedDeclarationStub { return visitor.visitParameter(this, data); } + //TODO: rename it to getTypeRef for consistency @Nullable public JetTypeReference getTypeReference() { return getStubOrPsiChild(JetStubElementTypes.TYPE_REFERENCE); } + @Nullable + public JetTypeReference setTypeRef(@Nullable JetTypeReference typeRef) { + return TypeRefHelpersPackage.setTypeRef(this, getNameIdentifier(), typeRef); + } + public boolean hasDefaultValue() { PsiJetParameterStub stub = getStub(); if (stub != null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java index 440d5353241..30bc9b0733b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetProperty.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import org.jetbrains.jet.lang.psi.stubs.PsiJetPropertyStub; import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes; +import org.jetbrains.jet.lang.psi.typeRefHelpers.TypeRefHelpersPackage; import org.jetbrains.jet.lexer.JetTokens; import java.util.List; @@ -121,6 +122,12 @@ public class JetProperty extends JetTypeParameterListOwnerStub()) + .firstOrNull() +} + +fun setTypeRef(declaration: JetNamedDeclaration, addAfter: PsiElement?, typeRef: JetTypeReference?): JetTypeReference? { + val oldTypeRef = getTypeRef(declaration) + if (typeRef != null) { + if (oldTypeRef != null) { + return oldTypeRef.replace(typeRef) as JetTypeReference + } + else { + var anchor = addAfter ?: declaration.getNameIdentifier() + val newTypeRef = declaration.addAfter(typeRef, anchor) as JetTypeReference + declaration.addAfter(JetPsiFactory(declaration.getProject()).createColon(), anchor) + return newTypeRef + } + } + else { + if (oldTypeRef != null) { + val colon = declaration.getNode()!!.findChildByType(JetTokens.COLON)!!.getPsi()!! + val removeFrom = colon.getPrevSibling() as? PsiWhiteSpace ?: colon + declaration.deleteChildRange(removeFrom, oldTypeRef) + } + return null + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java b/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java index 5eeeccdd07e..37528929314 100644 --- a/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java +++ b/idea/src/org/jetbrains/jet/plugin/intentions/SpecifyTypeExplicitlyAction.java @@ -61,7 +61,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { } @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element) { JetTypeReference typeRefParent = PsiTreeUtil.getTopmostParentOfType(element, JetTypeReference.class); if (typeRefParent != null) { element = typeRefParent; @@ -74,7 +74,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { addTypeAnnotation(project, editor, property, type); } else { - removeTypeAnnotation(property); + property.setTypeRef(null); } } else if (parent instanceof JetParameter) { @@ -83,7 +83,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { addTypeAnnotation(project, editor, parameter, type); } else { - removeTypeAnnotation(parameter); + parameter.setTypeRef(null); } } else if (parent instanceof JetNamedFunction) { @@ -97,7 +97,7 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { } @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + public boolean isAvailable(@NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element) { if (element.getContainingFile() instanceof JetCodeFragment) { return false; } @@ -181,43 +181,33 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { @NotNull JetProperty property, @NotNull JetType exprType ) { - if (property.getTypeRef() != null) { - return; - } + if (property.getTypeRef() != null) return; - PsiElement anchor = property.getNameIdentifier(); - if (anchor == null) { - return; - } - - addTypeAnnotation(project, editor, property, anchor, exprType); + addTypeAnnotationWithTemplate(project, editor, property, exprType); } public static void addTypeAnnotation(Project project, @Nullable Editor editor, JetFunction function, @NotNull JetType exprType) { - JetParameterList valueParameterList = function.getValueParameterList(); - assert valueParameterList != null; if (editor != null) { - addTypeAnnotation(project, editor, function, valueParameterList, exprType); + addTypeAnnotationWithTemplate(project, editor, function, exprType); } else { - addTypeAnnotationSilently(project, function, valueParameterList); + function.setReturnTypeRef(anyTypeRef(project)); } } public static void addTypeAnnotation(Project project, @Nullable Editor editor, JetParameter parameter, @NotNull JetType exprType) { if (editor != null) { - addTypeAnnotation(project, editor, parameter, parameter.getNameIdentifier(), exprType); + addTypeAnnotationWithTemplate(project, editor, parameter, exprType); } else { - addTypeAnnotationSilently(project, parameter, parameter.getNameIdentifier()); + parameter.setTypeRef(anyTypeRef(project)); } } - private static void addTypeAnnotation( + private static void addTypeAnnotationWithTemplate( @NotNull Project project, @NotNull Editor editor, @NotNull final JetNamedDeclaration namedDeclaration, - @NotNull PsiElement anchor, @NotNull JetType exprType ) { assert !exprType.isError() : "Unexpected error type: " + namedDeclaration.getText(); @@ -245,12 +235,13 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { } }; - addTypeAnnotationSilently(project, namedDeclaration, anchor); + setTypeRef(namedDeclaration, anyTypeRef(project)); PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); JetTypeReference newTypeRef = getTypeRef(namedDeclaration); + assert newTypeRef != null; TemplateBuilderImpl builder = new TemplateBuilderImpl(newTypeRef); builder.replaceElement(newTypeRef, expression); @@ -260,15 +251,15 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { manager.startTemplate(editor, builder.buildInlineTemplate(), new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { - ShortenReferences.INSTANCE$.process(getTypeRef(namedDeclaration)); + JetTypeReference typeRef = getTypeRef(namedDeclaration); + assert typeRef != null; + ShortenReferences.INSTANCE$.process(typeRef); } }); } - private static void addTypeAnnotationSilently(Project project, JetNamedDeclaration namedDeclaration, PsiElement anchor) { - JetPsiFactory psiFactory = JetPsiFactory(namedDeclaration); - namedDeclaration.addAfter(psiFactory.createType("Any"), anchor); - namedDeclaration.addAfter(psiFactory.createColon(), anchor); + private static JetTypeReference anyTypeRef(@NotNull Project project) { + return JetPsiFactory(project).createType("Any"); } @Nullable @@ -286,24 +277,18 @@ public class SpecifyTypeExplicitlyAction extends PsiElementBaseIntentionAction { return null; } - private static void removeTypeAnnotation(@Nullable PsiElement removeAfter, @Nullable JetTypeReference typeReference) { - if (removeAfter == null) return; - if (typeReference == null) return; - PsiElement sibling = removeAfter.getNextSibling(); - if (sibling == null) return; - PsiElement nextSibling = typeReference.getNextSibling(); - sibling.getParent().getNode().removeRange(sibling.getNode(), nextSibling == null ? null : nextSibling.getNode()); - } - - public static void removeTypeAnnotation(JetVariableDeclaration property) { - removeTypeAnnotation(property.getNameIdentifier(), property.getTypeRef()); - } - - public static void removeTypeAnnotation(JetParameter parameter) { - removeTypeAnnotation(parameter.getNameIdentifier(), parameter.getTypeReference()); - } - - public static void removeTypeAnnotation(JetFunction function) { - removeTypeAnnotation(function.getValueParameterList(), function.getReturnTypeRef()); + @Nullable + private static JetTypeReference setTypeRef(@NotNull JetNamedDeclaration namedDeclaration, @Nullable JetTypeReference typeRef) { + if (namedDeclaration instanceof JetProperty) { + return ((JetProperty) namedDeclaration).setTypeRef(typeRef); + } + else if (namedDeclaration instanceof JetParameter) { + return ((JetParameter) namedDeclaration).setTypeRef(typeRef); + } + else if (namedDeclaration instanceof JetFunction) { + return ((JetFunction) namedDeclaration).setReturnTypeRef(typeRef); + } + assert false : "Wrong namedDeclaration: " + namedDeclaration.getText(); + return null; } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java index 5a3f0349b5f..41dbe4e4725 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeFunctionReturnTypeFix.java @@ -43,7 +43,6 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; -import org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction; import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.LinkedList; @@ -109,7 +108,7 @@ public class ChangeFunctionReturnTypeFix extends JetIntentionAction changeFunctionLiteralReturnTypeFix.invoke(project, editor, file); } else { - SpecifyTypeExplicitlyAction.removeTypeAnnotation(element); + element.setReturnTypeRef(null); if (!(KotlinBuiltIns.getInstance().isUnit(type) && element.hasBlockBody())) { addReturnTypeAnnotation(element, renderedType); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java index 391a19ff280..0402f7530c3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableTypeFix.java @@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; -import org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction; import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.LinkedList; @@ -82,7 +81,7 @@ public class ChangeVariableTypeFix extends JetIntentionAction { } } if (changeInfo.isReturnTypeChanged()) { - SpecifyTypeExplicitlyAction.removeTypeAnnotation(function); + function.setReturnTypeRef(null); String returnTypeText = changeInfo.getNewReturnTypeText(); //TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java index bf81536a70b..b0da6cf08e8 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduce/introduceVariable/KotlinInplaceVariableIntroducer.java @@ -121,7 +121,7 @@ public class KotlinInplaceVariableIntroducer extends InplaceVariableIntroducer