Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import com.intellij.ui.{util => _, _}
import com.intellij.util.Consumer
import com.intellij.util.ui.table.{JBListTable, JBTableRowEditor, JBTableRowRenderer}
import com.intellij.util.ui.{StartupUiUtil, UIUtil}
import org.jetbrains.plugins.scala.extensions.invokeLater
import org.jetbrains.annotations.TestOnly
import org.jetbrains.plugins.scala.editor.DocumentExt
import org.jetbrains.plugins.scala.extensions.{inWriteAction, invokeLater}
import org.jetbrains.plugins.scala.icons.Icons
import org.jetbrains.plugins.scala.lang.psi.api.base.ScPrimaryConstructor
import org.jetbrains.plugins.scala.lang.psi.api.statements.ScFunction
Expand Down Expand Up @@ -67,13 +69,13 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,

override def createRefactoringProcessor(): BaseRefactoringProcessor = {
val parameters = splittedItems.map(_.map(_.parameter))

val changeInfo =
ScalaChangeInfo(getVisibility, method.fun, getMethodName, returnType, parameters, isAddDefaultArgs, Some(mySpecifyTypeChb.isSelected))

new ScalaChangeSignatureProcessor(changeInfo)
}

override def createNorthPanel(): JComponent = {
val panel = super.createNorthPanel()
getMethodName match {
Expand All @@ -90,27 +92,27 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
val optionsPanel = new JPanel(new BorderLayout())
val label = new JLabel(ScalaBundle.message("parameter.label.default.value"))
defaultValuesUsagePanel = new DefaultValuesUsagePanel("")

val holder = new JPanel()
holder.add(label)
holder.add(defaultValuesUsagePanel)

optionsPanel.add(holder)
optionsPanel
}

override def createOptionsPanel(): JComponent = {
val panel = super.createOptionsPanel() //to initialize fields in base class

val holder: JPanel = new JPanel
holder.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 0))

val specifyTypePanel = createTypePanel()
panel.add(specifyTypePanel)

panel.setVisible(needSpecifyTypeChb)
myPropagateParamChangesButton.setVisible(false)

panel
}

Expand Down Expand Up @@ -183,7 +185,7 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
override def createReturnTypeCodeFragment(): PsiCodeFragment = {
val text = method.returnTypeText
val child = method.fun
val fragment = ScalaCodeFragment(text, child.getParent, child)
val fragment = ScalaCodeFragment(text, child)
HighlightLevelUtil.forceRootHighlighting(fragment, FileHighlightingSetting.SKIP_HIGHLIGHTING)
fragment
}
Expand Down Expand Up @@ -227,12 +229,12 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
val paramsText = splittedItems.map(_.map(itemText).mkString("(", ", ", ")")).mkString

val retTypeText = returnTypeText

val needType =
if (!needSpecifyTypeChb) true
else if (mySpecifyTypeChb != null) mySpecifyTypeChb.isSelected
else needsTypeAnnotation(method, visibility)

val typeAnnot =
if (retTypeText.isEmpty || !needType) ""
else s": $retTypeText"
Expand Down Expand Up @@ -323,6 +325,20 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,

def parametersTable: JBTable = Option(myParametersList).map(_.getTable).orNull

@TestOnly
def setReturnType(text: String): Unit =
inWriteAction {
myReturnTypeField.getDocument.setText(text)
myReturnTypeField.getDocument.commit(project)
}

@TestOnly
def setParameter(idx: Int, name: String, `type`: String): Unit = {
val row = myParametersTableModel.getRowValue(idx)
row.parameter.name = name
row.typeText = `type`
}

protected def getDefaultValuesPanel: DefaultValuesUsagePanel = defaultValuesUsagePanel

protected def isAddDefaultArgs: Boolean = getDefaultValuesPanel.isAddDefaultArgs
Expand All @@ -331,7 +347,7 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,

protected def returnType: ScType =
Option(myReturnTypeCodeFragment).flatMap { fragment =>
createTypeFromText(fragment.getText, fragment.getContext, fragment)
createTypeFromText(fragment.getText, fragment, fragment)
}.getOrElse(api.Any)

protected def splittedItems: Seq[Seq[ScalaParameterTableModelItem]] = {
Expand All @@ -345,6 +361,7 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
firstClause +: inner(rest)
}
}

inner(parameterItems)
}

Expand Down Expand Up @@ -466,10 +483,10 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
@nowarn("cat=deprecation")
val buttonsPanel: JPanel =
ToolbarDecorator.createDecorator(table)
.setMoveUpAction(upAction)
.setMoveDownAction(downAction)
.addExtraActions(createAddClauseButton(), createRemoveClauseButton())
.createPanel
.setMoveUpAction(upAction)
.setMoveDownAction(downAction)
.addExtraActions(createAddClauseButton(), createRemoveClauseButton())
.createPanel
myParametersTableModel.addTableModelListener(mySignatureUpdater)
buttonsPanel
}
Expand All @@ -491,29 +508,29 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
}

private def editingColumn(table: JTable) = if (table.isEditing) Some(table.getEditingColumn) else None

private def createTypePanel(): JPanel = {
val typePanel = new JPanel
typePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0))

mySpecifyTypeChb = new JCheckBox
mySpecifyTypeChb.setText(ScalaBundle.message("specify.result.type"))
mySpecifyTypeChb.setDisplayedMnemonicIndex(15)

typePanel.add(mySpecifyTypeChb)

val myLinkContainer = new JPanel
myLinkContainer.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0))
typePanel.add(myLinkContainer)

myLinkContainer.add(setUpHyperLink())

setUpSpecifyTypeChb()
setUpVisibilityListener()

typePanel
}

private def setUpHyperLink(): HyperlinkLabel = {
val link = TypeAnnotationUtil.createTypeAnnotationsHLink(project, ScalaBundle.message("default.ta.settings"))

Expand All @@ -523,23 +540,23 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
updateSignatureAlarmFired()
}
})

link
}

private def setUpVisibilityListener(): Unit = {
myVisibilityPanel.addListener((_: ChangeEvent) => {
mySpecifyTypeChb.setSelected(needsTypeAnnotation(method))
updateSignatureAlarmFired()
})
}
private def setUpSpecifyTypeChb(): Unit ={

private def setUpSpecifyTypeChb(): Unit = {
mySpecifyTypeChb.setSelected(needsTypeAnnotation(method))

mySpecifyTypeChb.addActionListener((_: ActionEvent) => updateSignatureAlarmFired())
}

class ScalaParametersListTable extends ParametersListTable {
override protected def getRowRenderer(row: Int): JBTableRowRenderer = {
(_: JTable, row: Int, selected: Boolean, focused: Boolean) => {
Expand Down Expand Up @@ -577,7 +594,7 @@ class ScalaChangeSignatureDialog(val method: ScalaMethodDescriptor,
}

protected def typeText(item: ScalaParameterTableModelItem): String = {
val maxLength =parameterItems.map(_.typeText.length)
val maxLength = parameterItems.map(_.typeText.length)
.maxOption.getOrElse(0)
val typeText = item.typeText
typeText + StringUtil.repeat(" ", maxLength - typeText.length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class ScalaParameterTableModel(typeContext: PsiElement,
override def createRowItem(parameterInfo: ScalaParameterInfo): ScalaParameterTableModelItem = {
val info = Option(parameterInfo).getOrElse(ScalaParameterInfo(project))

val paramTypeCodeFragment = ScalaCodeFragment(info.typeText(typeContext), typeContext.getParent, typeContext)
val defaultValueCodeFragment = ScalaCodeFragment(info.getDefaultValue, defaultValueContext.getParent, defaultValueContext)
val paramTypeCodeFragment = ScalaCodeFragment(info.typeText(typeContext), typeContext)
val defaultValueCodeFragment = ScalaCodeFragment(info.getDefaultValue, defaultValueContext)

val fragments = Seq(paramTypeCodeFragment, defaultValueCodeFragment)
codeFragments ++= fragments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class ScalaParameterTableModelItem(parameter: ScalaParameterInfo,
problems += ScalaBundle.message("parameter.could.not.be.repeated.and.by.name")
}

parameter.scType = ScalaPsiElementFactory.createTypeElementFromText(trimmed, typeCodeFragment, typeCodeFragment) match {
val element = ScalaPsiElementFactory.createTypeElementFromText(trimmed, typeCodeFragment, typeCodeFragment)
parameter.scType = element match {
case Typeable(scType) => scType
case _ => null
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.jetbrains.plugins.scala.lang.refactoring.changeSignature

import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.EditorTestUtil.{CARET_TAG => Caret}
import com.intellij.ui.UiInterceptors
import org.jetbrains.plugins.scala.base.ScalaLightCodeInsightFixtureTestCase
import org.junit.Assert

class ScalaChangeSignatureTest extends ScalaLightCodeInsightFixtureTestCase {
def testGenerics(): Unit = {
val before =
s"""class MyObject[A] {
|
| def ${Caret}foo[B](a: A, b: B): B = ???
|}
|""".stripMargin
val after =
s"""class MyObject[A] {
|
| def foo[B](b1: B, b2: B): A = ???
|}""".stripMargin

doTest(before, after, Seq("b1" -> "B", "b2" -> "B"), "A")
}

def testHigherKindedTypes(): Unit = {
val before =
s"""class MyObject {
|
| def ${Caret}foo[F[_]](a: F[Int]): F[Int] = ???
|}
|""".stripMargin
val after =
s"""class MyObject {
|
| def foo[F[_]](b: F[String]): F[Unit] = ???
|}""".stripMargin

doTest(before, after, Seq("b" -> "F[String]"), "F[Unit]")
}

def testComplexHigherKindedTypes(): Unit = {
val before =
s"""class MyObject {
| type Mtl[F[_], A] = F[Option[A]]
|
| def ${Caret}foo[F[_], G[_]](a: Mtl[F, Int]): Mtl[G, Int] = ???
|}
|""".stripMargin
val after =
s"""class MyObject {
| type Mtl[F[_], A] = F[Option[A]]
|
| def foo[F[_], G[_]](a: Mtl[G, Int]): Mtl[F, Int] = ???
|}""".stripMargin

doTest(before, after, Seq("a" -> "Mtl[G, Int]"), "Mtl[F, Int]")
}

private def doTest(initialText: String, expectedText: String, parameters: Seq[(String, String)], returnType: String): Unit = {
doRefactoringAction(initialText, parameters, returnType)
Assert.assertEquals(expectedText, getFile.getText)
}

private def doRefactoringAction(fileText: String, parameters: Seq[(String, String)], returnType: String): Unit = {
scalaFixture.configureFromFileText(fileText)

UiInterceptors.register(new UiInterceptors.UiInterceptor[ScalaChangeSignatureDialog](classOf[ScalaChangeSignatureDialog]) {
override protected def doIntercept(dialog: ScalaChangeSignatureDialog): Unit = {
Disposer.register(getTestRootDisposable, dialog.getDisposable)
dialog.setReturnType(returnType)
parameters.zipWithIndex.foreach { case (name, typeText) -> idx =>
dialog.setParameter(idx, name, typeText)
}
dialog.performOKAction()
}
})

invokeChangeSignatureDialog()
}

private def invokeChangeSignatureDialog(): Unit = {
new ScalaChangeSignatureHandler().invoke(getProject, getEditor, getFile, DataContext.EMPTY_CONTEXT)
}
}