mirror of
https://github.com/ilyakooo0/intellij-haskell.git
synced 2024-08-17 10:40:44 +03:00
Initial support for reformatting by Ormolu by replacing custom Hindent and Stylish-Haskell paths by Ormolu path.
This commit is contained in:
parent
efe93aaf39
commit
537906a8c4
@ -21,4 +21,10 @@ object HTool {
|
||||
case object StylishHaskell extends HTool {
|
||||
def name: String = "stylish-haskell"
|
||||
}
|
||||
|
||||
case object Ormolu extends HTool {
|
||||
def name: String = "ormolu"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.{AnActionEvent, Presentation}
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import intellij.haskell.external.component.StackProjectManager
|
||||
import intellij.haskell.settings.HaskellSettingsState
|
||||
import intellij.haskell.util.{HaskellEditorUtil, HaskellFileUtil}
|
||||
|
||||
class HaskellReformatAction extends ReformatCodeAction {
|
||||
@ -32,7 +33,7 @@ class HaskellReformatAction extends ReformatCodeAction {
|
||||
ActionUtil.findActionContext(actionEvent).foreach(actionContext => {
|
||||
val psiFile = actionContext.psiFile
|
||||
if (HaskellFileUtil.isHaskellFile(psiFile)) {
|
||||
HaskellEditorUtil.enableExternalAction(actionEvent, (project: Project) => StackProjectManager.isStylishHaskellAvailable(project) && StackProjectManager.isHindentAvailable(project))
|
||||
HaskellEditorUtil.enableExternalAction(actionEvent, (project: Project) => (StackProjectManager.isStylishHaskellAvailable(project) && StackProjectManager.isHindentAvailable(project)) || HaskellReformatAction.reformatByOrmolu)
|
||||
} else {
|
||||
super.update(actionEvent)
|
||||
}
|
||||
@ -45,10 +46,10 @@ class HaskellReformatAction extends ReformatCodeAction {
|
||||
if (HaskellFileUtil.isHaskellFile(psiFile)) {
|
||||
val selectionModel = actionContext.selectionModel
|
||||
selectionModel match {
|
||||
case Some(_) =>
|
||||
case Some(_) if StackProjectManager.isHindentAvailable(actionEvent.getProject) =>
|
||||
HindentReformatAction.format(psiFile, selectionModel.map(m =>
|
||||
HindentReformatAction.translateSelectionModelToSelectionContext(m)))
|
||||
case None => HaskellReformatAction.reformatFile(psiFile)
|
||||
case _ => HaskellReformatAction.reformatFile(psiFile)
|
||||
}
|
||||
} else {
|
||||
super.actionPerformed(actionEvent)
|
||||
@ -59,9 +60,17 @@ class HaskellReformatAction extends ReformatCodeAction {
|
||||
|
||||
object HaskellReformatAction {
|
||||
|
||||
def reformatByOrmolu: Boolean = {
|
||||
HaskellSettingsState.ormoluPath.isDefined
|
||||
}
|
||||
|
||||
def reformatFile(psiFile: PsiFile): Boolean = {
|
||||
HindentReformatAction.format(psiFile)
|
||||
StylishHaskellReformatAction.format(psiFile)
|
||||
HaskellSettingsState.ormoluPath match {
|
||||
case Some(p) => OrmoluReformatAction.format(psiFile, p)
|
||||
case None =>
|
||||
HindentReformatAction.format(psiFile)
|
||||
StylishHaskellReformatAction.format(psiFile)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import intellij.haskell.external.component.StackProjectManager
|
||||
import intellij.haskell.external.execution.CommandLine
|
||||
import intellij.haskell.settings.HaskellSettingsState
|
||||
import intellij.haskell.util._
|
||||
import intellij.haskell.{GlobalInfo, HTool, HaskellLanguage, HaskellNotificationGroup}
|
||||
|
||||
@ -52,7 +51,7 @@ class HindentReformatAction extends AnAction {
|
||||
}
|
||||
|
||||
object HindentReformatAction {
|
||||
private def hindentPath = HaskellSettingsState.hindentPath.getOrElse(GlobalInfo.defaultHindentPath.toString)
|
||||
private def hindentPath = GlobalInfo.defaultHindentPath.toString
|
||||
|
||||
def format(psiFile: PsiFile, selectionContext: Option[SelectionContext] = None): Boolean = {
|
||||
val lineLength = CodeStyle.getSettings(psiFile.getProject).getRightMargin(HaskellLanguage.Instance)
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014-2019 Rik van der Kleij
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package intellij.haskell.action
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.actionSystem.{AnAction, AnActionEvent}
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import intellij.haskell.external.execution.CommandLine
|
||||
import intellij.haskell.settings.HaskellSettingsState
|
||||
import intellij.haskell.util._
|
||||
import intellij.haskell.{HTool, HaskellNotificationGroup}
|
||||
|
||||
sealed case class SelectionContext(start: Int, end: Int, text: String)
|
||||
|
||||
class OrmoluReformatAction extends AnAction {
|
||||
|
||||
override def update(actionEvent: AnActionEvent): Unit = {
|
||||
HaskellEditorUtil.enableExternalAction(actionEvent, (project: Project) => HaskellReformatAction.reformatByOrmolu)
|
||||
}
|
||||
|
||||
override def actionPerformed(actionEvent: AnActionEvent): Unit = {
|
||||
ActionUtil.findActionContext(actionEvent).foreach { actionContext =>
|
||||
val psiFile = actionContext.psiFile
|
||||
HaskellSettingsState.ormoluPath match {
|
||||
case Some(p) => OrmoluReformatAction.format(psiFile, p)
|
||||
case None => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object OrmoluReformatAction {
|
||||
|
||||
def format(psiFile: PsiFile, ormoluPath: String): Unit = {
|
||||
val project = psiFile.getProject
|
||||
HaskellFileUtil.saveFile(psiFile)
|
||||
|
||||
HaskellFileUtil.getAbsolutePath(psiFile) match {
|
||||
case Some(path) =>
|
||||
val processOutputFuture = ApplicationManager.getApplication.executeOnPooledThread(ScalaUtil.callable[ProcessOutput] {
|
||||
CommandLine.run(project, ormoluPath, Seq(path))
|
||||
})
|
||||
|
||||
FutureUtil.waitForValue(project, processOutputFuture, s"reformatting by ${HTool.Ormolu.name}") match {
|
||||
case None => ()
|
||||
case Some(processOutput) =>
|
||||
if (processOutput.getStderrLines.isEmpty) {
|
||||
HaskellFileUtil.saveFileWithNewContent(psiFile, processOutput.getStdout)
|
||||
} else {
|
||||
HaskellNotificationGroup.logInfoEvent(project, s"Error while reformatting by `${HTool.Ormolu.name}`. Error: ${processOutput.getStderr}")
|
||||
}
|
||||
}
|
||||
case None => HaskellNotificationGroup.logWarningBalloonEvent(psiFile.getProject, s"Can not reformat file because could not determine path for file `${psiFile.getName}`. File exists only in memory")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def versionInfo(project: Project): String = {
|
||||
HaskellSettingsState.ormoluPath.map(p => CommandLine.run(project, p, Seq("--version")).getStdout).getOrElse("-")
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import intellij.haskell.external.component.StackProjectManager
|
||||
import intellij.haskell.external.execution.CommandLine
|
||||
import intellij.haskell.settings.HaskellSettingsState
|
||||
import intellij.haskell.util.{FutureUtil, HaskellEditorUtil, HaskellFileUtil, ScalaUtil}
|
||||
import intellij.haskell.{GlobalInfo, HTool, HaskellNotificationGroup}
|
||||
|
||||
@ -41,7 +40,7 @@ class StylishHaskellReformatAction extends AnAction {
|
||||
}
|
||||
|
||||
object StylishHaskellReformatAction {
|
||||
private def stylishHaskellPath = HaskellSettingsState.stylishHaskellPath.getOrElse(GlobalInfo.defaultStylishHaskellPath.toString)
|
||||
private def stylishHaskellPath = GlobalInfo.defaultStylishHaskellPath.toString
|
||||
|
||||
def versionInfo(project: Project): String = {
|
||||
if (StackProjectManager.isStylishHaskellAvailable(project)) {
|
||||
|
@ -75,7 +75,7 @@ object CommandLine {
|
||||
val commandLine = createCommandLine(workDir, commandPath, arguments)
|
||||
|
||||
if (!logOutput) {
|
||||
HaskellNotificationGroup.logInfoEvent(project, s"Executing: `${commandLine.getCommandLineString}`")
|
||||
HaskellNotificationGroup.logInfoEvent(project, s"Executing: ${commandLine.getCommandLineString} ")
|
||||
}
|
||||
|
||||
val processHandler = createProcessHandler(project, commandLine, logOutput)
|
||||
|
@ -34,6 +34,7 @@ class HaskellConfigurable extends Configurable {
|
||||
private val hindentPathField = new JTextField
|
||||
private val hlintPathField = new JTextField
|
||||
private val hooglePathField = new JTextField
|
||||
private val ormoluPathField = new JTextField
|
||||
private val stylishHaskellPathField = new JTextField
|
||||
private val useCustomToolsToggle = new JCheckBox
|
||||
private val extraStackArgumentsField = new JTextField
|
||||
@ -54,6 +55,7 @@ class HaskellConfigurable extends Configurable {
|
||||
hlintPathField.setVisible(visible)
|
||||
hooglePathField.setVisible(visible)
|
||||
stylishHaskellPathField.setVisible(visible)
|
||||
ormoluPathField.setVisible(visible)
|
||||
}
|
||||
|
||||
toggleToolPathsVisibility()
|
||||
@ -68,10 +70,9 @@ class HaskellConfigurable extends Configurable {
|
||||
hlintOptionsField.getDocument.addDocumentListener(docListener)
|
||||
replTimeoutField.getDocument.addDocumentListener(docListener)
|
||||
newProjectTemplateNameField.getDocument.addDocumentListener(docListener)
|
||||
hindentPathField.getDocument.addDocumentListener(docListener)
|
||||
hlintPathField.getDocument.addDocumentListener(docListener)
|
||||
hooglePathField.getDocument.addDocumentListener(docListener)
|
||||
stylishHaskellPathField.getDocument.addDocumentListener(docListener)
|
||||
ormoluPathField.getDocument.addDocumentListener(docListener)
|
||||
useSystemGhcToggle.addChangeListener { _ =>
|
||||
isModifiedByUser = true
|
||||
}
|
||||
@ -126,10 +127,9 @@ class HaskellConfigurable extends Configurable {
|
||||
(new JLabel(NewProjectTemplateName), newProjectTemplateNameField),
|
||||
(new JLabel(BuildToolsUsingSystemGhc), useSystemGhcToggle),
|
||||
(new JLabel(UseCustomTool), useCustomToolsToggle),
|
||||
(new JLabel(HindentPath), hindentPathField),
|
||||
(new JLabel(HlintPath), hlintPathField),
|
||||
(new JLabel(HooglePath), hooglePathField),
|
||||
(new JLabel(StylishHaskellPath), stylishHaskellPathField),
|
||||
(new JLabel(OrmoluPath), ormoluPathField),
|
||||
(new JLabel(""), afterRestartLabel)
|
||||
)
|
||||
|
||||
@ -163,10 +163,9 @@ class HaskellConfigurable extends Configurable {
|
||||
state.hlintOptions = hlintOptionsField.getText
|
||||
state.useSystemGhc = useSystemGhcToggle.isSelected
|
||||
state.newProjectTemplateName = newProjectTemplateNameField.getText
|
||||
state.hindentPath = hindentPathField.getText
|
||||
state.hlintPath = hlintPathField.getText
|
||||
state.hooglePath = hooglePathField.getText
|
||||
state.stylishHaskellPath = stylishHaskellPathField.getText
|
||||
state.ormoluPath = ormoluPathField.getText
|
||||
state.customTools = useCustomToolsToggle.isSelected
|
||||
state.extraStackArguments = extraStackArgumentsField.getText
|
||||
}
|
||||
@ -192,17 +191,16 @@ class HaskellConfigurable extends Configurable {
|
||||
|
||||
private def validateCustomTools(): Unit = {
|
||||
if (useCustomToolsToggle.isSelected) {
|
||||
if (hindentPathField.getText.trim.isEmpty ||
|
||||
hlintPathField.getText.trim.isEmpty ||
|
||||
hooglePathField.getText.trim.isEmpty ||
|
||||
stylishHaskellPathField.getText.trim.isEmpty) {
|
||||
if (
|
||||
ormoluPathField.getText.trim.isEmpty ||
|
||||
hlintPathField.getText.trim.isEmpty ||
|
||||
hooglePathField.getText.trim.isEmpty) {
|
||||
throw new ConfigurationException(s"All Haskell tools paths have to be set")
|
||||
}
|
||||
|
||||
checkFileExists(hindentPathField.getText)
|
||||
checkFileExists(hlintPathField.getText)
|
||||
checkFileExists(hooglePathField.getText)
|
||||
checkFileExists(stylishHaskellPathField.getText)
|
||||
checkFileExists(ormoluPathField.getText)
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,10 +215,9 @@ class HaskellConfigurable extends Configurable {
|
||||
useSystemGhcToggle.setSelected(state.useSystemGhc)
|
||||
replTimeoutField.setText(state.replTimeout.toString)
|
||||
newProjectTemplateNameField.setText(state.newProjectTemplateName)
|
||||
hindentPathField.setText(state.hindentPath)
|
||||
hlintPathField.setText(state.hlintPath)
|
||||
hooglePathField.setText(state.hooglePath)
|
||||
stylishHaskellPathField.setText(state.stylishHaskellPath)
|
||||
ormoluPathField.setText(state.ormoluPath)
|
||||
useCustomToolsToggle.setSelected(state.customTools)
|
||||
extraStackArgumentsField.setText(state.extraStackArguments)
|
||||
}
|
||||
@ -235,6 +232,7 @@ object HaskellConfigurable {
|
||||
final val HlintPath = "Hlint path"
|
||||
final val HooglePath = "Hoogle path"
|
||||
final val StylishHaskellPath = "Stylish Haskell path"
|
||||
final val OrmoluPath = "Ormolu path"
|
||||
final val UseCustomTool = "Use custom Haskell tools *"
|
||||
final val CustomToolPathWarning =
|
||||
"""WARNING! Specifying a path for a Haskell tool will override the default
|
||||
|
@ -54,10 +54,9 @@ public class HaskellSettingsPersistentStateComponent implements PersistentStateC
|
||||
public Boolean reformatCodeBeforeCommit = false;
|
||||
public Boolean optimizeImportsBeforeCommit = false;
|
||||
public String newProjectTemplateName = "new-template";
|
||||
public String hindentPath = "";
|
||||
public String hlintPath = "";
|
||||
public String hooglePath = "";
|
||||
public String stylishHaskellPath = "";
|
||||
public String ormoluPath = "";
|
||||
public Boolean customTools = false;
|
||||
public String extraStackArguments = "";
|
||||
}
|
||||
|
@ -55,10 +55,6 @@ object HaskellSettingsState {
|
||||
state.customTools
|
||||
}
|
||||
|
||||
def hindentPath: Option[String] = {
|
||||
Option.when(customTools && state.hindentPath.nonEmpty)(state.hindentPath)
|
||||
}
|
||||
|
||||
def hlintPath: Option[String] = {
|
||||
Option.when(customTools && state.hlintPath.nonEmpty)(state.hlintPath)
|
||||
}
|
||||
@ -67,8 +63,8 @@ object HaskellSettingsState {
|
||||
Option.when(customTools && state.hooglePath.nonEmpty)(state.hooglePath)
|
||||
}
|
||||
|
||||
def stylishHaskellPath: Option[String] = {
|
||||
Option.when(customTools && state.stylishHaskellPath.nonEmpty)(state.stylishHaskellPath)
|
||||
def ormoluPath: Option[String] = {
|
||||
Option.when(customTools && state.ormoluPath.nonEmpty)(state.ormoluPath)
|
||||
}
|
||||
|
||||
def useCustomTools: Boolean = {
|
||||
|
Loading…
Reference in New Issue
Block a user