Compare commits

...

4 Commits

Author SHA1 Message Date
Nikolay Krasko
28f42ba804 -- very temp 2018-09-03 03:45:00 +03:00
Nikolay Krasko
bf6efe27b1 -- use designer for load/save tab 2018-08-22 18:21:42 +03:00
Nikolay Krasko
bb115881b7 Add heuristic for old code style and update notification rules (KT-23400)
Don't show notification for new projects
Don't show notification if user doesn't edit kotlin files
Don't show notification when recent files have new code style
2018-08-13 11:33:00 +03:00
Nikolay Krasko
1854c67086 Refactoring: move code style notifications to common idea module 2018-08-13 11:32:59 +03:00
15 changed files with 543 additions and 243 deletions

View File

@@ -1,104 +1,7 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="140" />
<JavaCodeStyleSettings>
<option name="PREFER_LONGER_NAMES" value="false" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value>
<package name="java.awt" withSubpackages="false" static="false" />
<package name="javax.tools" withSubpackages="true" static="false" />
<package name="javax.swing" withSubpackages="false" static="false" />
</value>
</option>
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<MarkdownNavigatorCodeStyleSettings>
<option name="RIGHT_MARGIN" value="72" />
</MarkdownNavigatorCodeStyleSettings>
<codeStyleSettings language="HTML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="5" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
</codeStyleSettings>
<codeStyleSettings language="PROTO">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,5 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@@ -4,7 +4,7 @@
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="scriptParameters" value="--parallel" />
<option name="taskDescriptions">
<list />
</option>
@@ -15,6 +15,6 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
<method v="2" />
</configuration>
</component>

View File

@@ -65,6 +65,9 @@ public class KotlinCodeStyleSettings extends CustomCodeStyleSettings {
@ReflectionUtil.SkipInEquals
public String CODE_STYLE_DEFAULTS = null;
@ReflectionUtil.SkipInEquals
public boolean OVERRIDE_PROJECT_DEFAULTS = false;
/**
* Load settings with previous IDEA defaults to have an ability to restore them.
*/

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
import com.google.common.annotations.VisibleForTesting
import com.google.common.base.Joiner
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.project.Project
import com.intellij.util.SystemProperties
import org.jetbrains.annotations.NonNls
import java.io.File
import java.io.IOException
import java.util.*
fun getBaseDirPath(project: Project): File {
val basePath = project.basePath!!
return File(ExternalSystemApiUtil.toCanonicalPath(basePath))
}
class GradleProperties @Throws(IOException::class) constructor(val path: File) {
val properties: Properties
@Throws(IOException::class)
constructor(project: Project) : this(File(getBaseDirPath(project), "gradle.properties"))
init {
properties = PropertiesFiles.getProperties(this.path)
}
@VisibleForTesting
internal fun getProperty(name: String): String? {
return properties.getProperty(name)
}
@Throws(IOException::class)
fun save() {
PropertiesFiles.savePropertiesToFile(properties, path, headerComment)
}
fun clear() {
properties.clear()
}
companion object {
@NonNls
private val JVM_ARGS_PROPERTY_NAME = "org.gradle.jvmargs"
private val headerComment: String
get() {
val lines = arrayOf(
"# For more details on how to configure your build environment visit",
"# http://www.gradle.org/docs/current/userguide/build_environment.html",
"",
"# Specifies the JVM arguments used for the daemon process.",
"# The setting is particularly useful for tweaking memory settings.",
"# Default value: -Xmx1024m -XX:MaxPermSize=256m",
"# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8",
"",
"# When configured, Gradle will run in incubating parallel mode.",
"# This option should only be used with decoupled projects. More details, visit",
"# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects",
"# org.gradle.parallel=true"
)
return Joiner.on(SystemProperties.getLineSeparator()).join(lines)
}
}
}

View File

@@ -32,6 +32,8 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.impl.libraries.LibraryImpl
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.util.Key
import com.intellij.psi.codeStyle.CodeStyleSchemes
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
@@ -112,6 +114,16 @@ class KotlinGradleProjectDataService : AbstractProjectDataService<ModuleData, Vo
val kotlinFacet = configureFacetByGradleModule(ideModule, modelsProvider, moduleNode, null) ?: continue
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, moduleNode) }
}
val property = GradleProperties(project).getProperty("kotlin.code.style")
if (property != null) {
val schemeManager = CodeStyleSettingsManager.getInstance(project)
val currentScheme = CodeStyleSchemes.getInstance().findPreferredScheme(schemeManager.PREFERRED_PROJECT_CODE_STYLE)
if (currentScheme.isDefault) {
}
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration
import com.google.common.base.Charsets
import com.intellij.openapi.util.io.FileUtil
import java.io.*
import java.util.*
object PropertiesFiles {
@Throws(IOException::class)
fun getProperties(filePath: File): Properties {
if (filePath.isDirectory) {
throw IllegalArgumentException(String.format("The path '%1\$s' belongs to a directory!", filePath.path))
}
if (!filePath.exists()) {
return Properties()
}
val properties = Properties()
InputStreamReader(BufferedInputStream(FileInputStream(filePath)), Charsets.UTF_8).use { reader -> properties.load(reader) }
return properties
}
@Throws(IOException::class)
fun savePropertiesToFile(properties: Properties, filePath: File, comments: String?) {
FileUtil.createParentDirs(filePath)
FileOutputStream(filePath).use { out ->
// Note that we don't write the properties files in UTF-8; this will *not* write the
// files with the default platform encoding; instead, it will write it using ISO-8859-1 and
// \\u escaping syntax for other characters. This will work with older versions of the Gradle
// plugin which does not read the .properties file with UTF-8 encoding. In the future when
// nobody is using older (0.7.x) versions of the Gradle plugin anymore we can upgrade this
properties.store(out, comments)
}
}
}

View File

@@ -1,108 +0,0 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration.ui.notifications
import com.intellij.ide.util.PropertiesComponent
import com.intellij.notification.*
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.kotlin.idea.formatter.*
import org.jetbrains.kotlin.idea.util.isDefaultOfficialCodeStyle
private const val KOTLIN_UPDATE_CODE_STYLE_GROUP_ID = "Update Kotlin code style"
private const val KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME = "update.kotlin.code.style.notified"
fun notifyKotlinStyleUpdateIfNeeded(project: Project) {
if (!isDefaultOfficialCodeStyle) return
@Suppress("DEPRECATION") // Suggested fix is absent in 173. BUNCH: 181
val isProjectSettings = CodeStyleSettingsManager.getInstance(project).USE_PER_PROJECT_SETTINGS
val settingsComponent: PropertiesComponent = if (isProjectSettings) {
PropertiesComponent.getInstance(project)
} else {
PropertiesComponent.getInstance()
}
if (settingsComponent.getBoolean(KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME, false)) {
return
}
val notification = KotlinCodeStyleChangedNotification.create(project, isProjectSettings) ?: return
notification.isImportant = true
NotificationsConfiguration.getNotificationsConfiguration()
.register(KOTLIN_UPDATE_CODE_STYLE_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
if (ApplicationManager.getApplication().isUnitTestMode) {
return
}
settingsComponent.setValue(KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME, true, false)
notification.notify(project)
}
private class KotlinCodeStyleChangedNotification(val project: Project, isProjectSettings: Boolean) : Notification(
KOTLIN_UPDATE_CODE_STYLE_GROUP_ID,
"Kotlin Code Style",
"""
<html>
Default code style was updated to Kotlin Coding Conventions.
</html>
""".trimIndent(),
NotificationType.WARNING,
null
) {
init {
val ktFormattingSettings = ktCodeStyleSettings(project)
if (isProjectSettings) {
addAction(object : NotificationAction("Apply new code style") {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
notification.expire()
val ktSettings = ktCodeStyleSettings(project) ?: return
runWriteAction {
KotlinStyleGuideCodeStyle.apply(ktSettings.all)
}
}
})
}
if (ktFormattingSettings != null && ktFormattingSettings.canRestore()) {
addAction(object : NotificationAction("Restore old settings") {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
notification.expire()
val ktSettings = ktCodeStyleSettings(project) ?: return
runWriteAction {
ktSettings.restore()
}
}
})
}
}
companion object {
val LOG = Logger.getInstance("KotlinCodeStyleChangedNotification")
fun create(project: Project, isProjectSettings: Boolean): KotlinCodeStyleChangedNotification? {
val ktFormattingSettings = ktCodeStyleSettings(project) ?: return null
if (isProjectSettings && !ktFormattingSettings.hasDefaultLoadScheme()) {
return null
}
return KotlinCodeStyleChangedNotification(project, isProjectSettings)
}
}
}

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.actions.internal
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.ui.Messages
import org.jetbrains.kotlin.idea.configuration.ui.notifications.KotlinCodeStyleChangedNotification
import org.jetbrains.kotlin.idea.formatter.KotlinFormatterUsageCollector
class KotlinFormattingSettingsStatusAction : AnAction() {
@@ -15,10 +16,14 @@ class KotlinFormattingSettingsStatusAction : AnAction() {
val project = e?.project ?: return
val formatterKind = KotlinFormatterUsageCollector.getKotlinFormatterKind(project)
val oldStyleRecentFile = KotlinCodeStyleChangedNotification.findRecentFileWithOldCodeStyle(project)
Messages.showInfoMessage(
project,
"formatterKind = $formatterKind",
"""
Formatter kind: $formatterKind
Probably old style: ${oldStyleRecentFile?.name ?: "No"}
""".trimIndent(),
"Kotlin Formatter Settings"
)
}

View File

@@ -0,0 +1,239 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.configuration.ui.notifications
import com.intellij.ide.util.PropertiesComponent
import com.intellij.notification.*
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.search.ProjectScope
import com.intellij.util.ThreeState
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.formatter.*
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.isDefaultOfficialCodeStyle
private const val KOTLIN_UPDATE_CODE_STYLE_GROUP_ID = "Update Kotlin code style"
private const val KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME = "update.kotlin.code.style.notified"
fun notifyKotlinStyleUpdateIfNeeded(project: Project) {
if (!isDefaultOfficialCodeStyle) return
@Suppress("DEPRECATION") // Suggested fix is absent in 173. BUNCH: 181
val isProjectSettings = CodeStyleSettingsManager.getInstance(project).USE_PER_PROJECT_SETTINGS
val settingsComponent: PropertiesComponent = if (isProjectSettings) {
PropertiesComponent.getInstance(project)
} else {
PropertiesComponent.getInstance()
}
if (settingsComponent.getBoolean(KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME, false)) {
return
}
val notification = KotlinCodeStyleChangedNotification.create(project, isProjectSettings) ?: return
notification.isImportant = true
NotificationsConfiguration.getNotificationsConfiguration()
.register(KOTLIN_UPDATE_CODE_STYLE_GROUP_ID, NotificationDisplayType.STICKY_BALLOON, true)
if (ApplicationManager.getApplication().isUnitTestMode) {
return
}
settingsComponent.setValue(KOTLIN_UPDATE_CODE_STYLE_PROPERTY_NAME, true, false)
notification.notify(project)
}
class KotlinCodeStyleChangedNotification(val project: Project, isProjectSettings: Boolean) : Notification(
KOTLIN_UPDATE_CODE_STYLE_GROUP_ID,
"Kotlin Code Style",
"""
<html>
Default code style was updated to Kotlin Coding Conventions.
</html>
""".trimIndent(),
NotificationType.WARNING,
null
) {
init {
val ktFormattingSettings = ktCodeStyleSettings(project)
if (isProjectSettings) {
addAction(object : NotificationAction("Apply new code style") {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
notification.expire()
val ktSettings = ktCodeStyleSettings(project) ?: return
runWriteAction {
KotlinStyleGuideCodeStyle.apply(ktSettings.all)
}
}
})
}
if (ktFormattingSettings != null && ktFormattingSettings.canRestore()) {
addAction(object : NotificationAction("Restore old settings") {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
notification.expire()
val ktSettings = ktCodeStyleSettings(project) ?: return
runWriteAction {
ktSettings.restore()
}
}
})
}
}
companion object {
val LOG = Logger.getInstance("KotlinCodeStyleChangedNotification")
fun create(project: Project, isProjectSettings: Boolean): KotlinCodeStyleChangedNotification? {
val ktFormattingSettings = ktCodeStyleSettings(project) ?: return null
if (isProjectSettings && !ktFormattingSettings.hasDefaultLoadScheme()) {
return null
}
if (findRecentFileWithOldCodeStyle(project) == null) {
// User doesn't have recent Kotlin files, or all files are formatted with new code style
return null
}
return KotlinCodeStyleChangedNotification(project, isProjectSettings)
}
fun findRecentFileWithOldCodeStyle(project: Project): PsiFile? {
val (isOldStyleDetected, oldStyleFiles) = detectIsOldCodeStyleFromRecentFiles(
project
)
if (isOldStyleDetected != ThreeState.YES) {
return null
}
return oldStyleFiles.firstOrNull()
}
private data class OldCodeStyleDetectionResult(
val result: ThreeState,
val oldStyleFiles: Collection<PsiFile>
) {
companion object {
val UNSURE =
OldCodeStyleDetectionResult(
ThreeState.UNSURE,
emptyList()
)
}
}
private fun detectIsOldCodeStyleFromRecentFiles(project: Project): OldCodeStyleDetectionResult {
val scope = KotlinSourceFilterScope.projectSources(ProjectScope.getContentScope(project), project)
val psiManager = PsiManager.getInstance(project)
val recentKotlinFiles = EditorHistoryManager.getInstance(project).fileList
.filter { it.fileType == KotlinFileType.INSTANCE }
.filter { it in scope }
.mapNotNull { psiManager.findFile(it) }
if (recentKotlinFiles.isEmpty()) {
return OldCodeStyleDetectionResult.UNSURE
}
val indentWhitespace =
indentWhitespace(
project
)
if (indentWhitespace == null || indentWhitespace.isEmpty()) {
return OldCodeStyleDetectionResult.UNSURE
}
val detectToFiles: Map<ThreeState, List<PsiFile>> = recentKotlinFiles
.groupBy { file ->
detectOldCodeStyle(
file,
indentWhitespace
)
}
val oldStyleFiles = detectToFiles[ThreeState.YES] ?: emptyList()
val newStyleFiles = detectToFiles[ThreeState.NO] ?: emptyList()
return when {
!oldStyleFiles.isEmpty() && !newStyleFiles.isEmpty() ->
OldCodeStyleDetectionResult.UNSURE
!oldStyleFiles.isEmpty() ->
OldCodeStyleDetectionResult(
ThreeState.YES,
oldStyleFiles
)
else ->
OldCodeStyleDetectionResult(
ThreeState.NO,
emptyList()
)
}
}
private fun indentWhitespace(project: Project): String? {
val indentOptions = ktCodeStyleSettings(project)?.common?.indentOptions ?: return null
return if (indentOptions.USE_TAB_CHARACTER) "\t" else " ".repeat(indentOptions.INDENT_SIZE)
}
private fun detectOldCodeStyle(ktFile: PsiFile, indentWhitespace: String): ThreeState {
val doubleIndent = indentWhitespace + indentWhitespace
var probablyOldStyleScore = 0
var probablyNewCodeStyle = 0
val text = runReadAction { ktFile.text } ?: return ThreeState.UNSURE
val lines = text.lines()
if (lines.size <= 1) return ThreeState.UNSURE
for (i in 1..(lines.size - 1)) {
val previous = lines[i - 1].trimEnd()
val next = lines[i].trimEnd()
if (previous.endsWith("(") || previous.endsWith("?:") || previous.endsWith("=") ||
next.startsWith(".") || next.startsWith("?.")
) {
val previousIndent = previous.takeWhile { it.isWhitespace() }
val nextIndent = next.takeWhile { it.isWhitespace() }
val indent = if (previousIndent.isEmpty()) nextIndent else nextIndent.substringAfter(previousIndent, "")
if (!indent.isEmpty()) {
if (indent == doubleIndent) {
probablyOldStyleScore++
} else if (indent == indentWhitespace) {
probablyNewCodeStyle++
}
}
}
}
return when {
probablyOldStyleScore > probablyNewCodeStyle -> ThreeState.YES
probablyOldStyleScore < probablyNewCodeStyle -> ThreeState.NO
else -> ThreeState.UNSURE
}
}
}
}

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.idea.formatter.Dialog">
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="5c703" class="javax.swing.JRadioButton" binding="enableProjectCodeStyleRadioButton" default-binding="true">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Enable project code style with obsolete code style and share it in VCS"/>
</properties>
</component>
<vspacer id="d426c">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="659a9" class="javax.swing.JRadioButton" binding="enableNewCodeStyleRadioButton" default-binding="true">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Enable new code style and share it in .idea folder with teammates"/>
</properties>
</component>
<component id="43648" class="javax.swing.JRadioButton" binding="useLocalCodeStyleRadioButton" default-binding="true">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Use local code style settings with obsolete code style"/>
</properties>
</component>
<component id="79be5" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Label"/>
</properties>
</component>
</children>
</grid>
</form>

View File

@@ -0,0 +1,14 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.formatter;
import javax.swing.*;
public class Dialog {
private JRadioButton enableProjectCodeStyleRadioButton;
private JRadioButton enableNewCodeStyleRadioButton;
private JRadioButton useLocalCodeStyleRadioButton;
}

View File

@@ -7,17 +7,8 @@ package org.jetbrains.kotlin.idea.formatter
import com.intellij.application.options.CodeStyleAbstractPanel
import com.intellij.openapi.editor.colors.EditorColorsScheme
import com.intellij.openapi.ui.ComboBox
import com.intellij.psi.codeStyle.CodeStyleSettings
import com.intellij.ui.ListCellRendererWrapper
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.panels.HorizontalLayout
import com.intellij.ui.components.panels.VerticalLayout
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import java.awt.BorderLayout
import javax.swing.BorderFactory
import javax.swing.JLabel
import javax.swing.JList
import javax.swing.JPanel
@@ -31,14 +22,13 @@ class KotlinSaveStylePanel(settings: CodeStyleSettings) : CodeStyleAbstractPanel
private data class SaveItem(val label: String, val id: String?)
private val saveDefaultsComboBox = ComboBox<SaveItem>()
private val saveDefaultsItems = listOf(
SaveItem("<ide defaults>", null),
SaveItem(KotlinObsoleteCodeStyle.CODE_STYLE_TITLE, KotlinObsoleteCodeStyle.CODE_STYLE_ID),
SaveItem(KotlinStyleGuideCodeStyle.CODE_STYLE_TITLE, KotlinStyleGuideCodeStyle.CODE_STYLE_ID)
)
var selectedId: String?
private var selectedId: String?
get() {
val (_, id) = saveDefaultsComboBox.selectedItem as SaveItem
return id
@@ -47,44 +37,37 @@ class KotlinSaveStylePanel(settings: CodeStyleSettings) : CodeStyleAbstractPanel
saveDefaultsComboBox.selectedItem = saveDefaultsItems.firstOrNull { (_, id) -> id == value } ?: saveDefaultsItems.first()
}
private val jPanel = JPanel(BorderLayout()).apply {
add(
JBScrollPane(
JPanel(VerticalLayout(JBUI.scale(5))).apply {
border = BorderFactory.createEmptyBorder(UIUtil.DEFAULT_VGAP, 10, UIUtil.DEFAULT_VGAP, 10)
add(JPanel(HorizontalLayout(JBUI.scale(5))).apply {
saveDefaultsItems.forEach {
saveDefaultsComboBox.addItem(it)
}
private val loadSaveCodeStyleForm = LoadSaveCodeStyleForm().apply {
saveDefaultsItems.forEach {
saveDefaultsComboBox.addItem(it)
}
saveDefaultsComboBox.setRenderer(object : ListCellRendererWrapper<SaveItem>() {
override fun customize(list: JList<*>?, value: SaveItem, index: Int, selected: Boolean, hasFocus: Boolean) {
setText(value.label)
}
})
add(JLabel("Use defaults from:"))
add(saveDefaultsComboBox)
})
}
)
)
saveDefaultsComboBox.setRenderer(object : ListCellRendererWrapper<SaveItem>() {
override fun customize(list: JList<*>?, value: SaveItem, index: Int, selected: Boolean, hasFocus: Boolean) {
setText(value.label)
}
})
}
private val saveDefaultsComboBox get() = loadSaveCodeStyleForm.saveDefaultsComboBox
override fun apply(settings: CodeStyleSettings) {
settings.kotlinCustomSettings.CODE_STYLE_DEFAULTS = selectedId
settings.kotlinCommonSettings.CODE_STYLE_DEFAULTS = selectedId
settings.kotlinCustomSettings.OVERRIDE_PROJECT_DEFAULTS = loadSaveCodeStyleForm.useDefaultObsoleteCodeCheckBox.isSelected
}
override fun isModified(settings: CodeStyleSettings): Boolean {
return selectedId != settings.kotlinCustomSettings.CODE_STYLE_DEFAULTS ||
selectedId != settings.kotlinCommonSettings.CODE_STYLE_DEFAULTS
selectedId != settings.kotlinCommonSettings.CODE_STYLE_DEFAULTS ||
loadSaveCodeStyleForm.useDefaultObsoleteCodeCheckBox.isSelected != settings.kotlinCustomSettings.OVERRIDE_PROJECT_DEFAULTS
}
override fun getPanel() = jPanel
override fun getPanel(): JPanel = loadSaveCodeStyleForm.panel
override fun resetImpl(settings: CodeStyleSettings) {
selectedId = settings.kotlinCustomSettings.CODE_STYLE_DEFAULTS ?: settings.kotlinCommonSettings.CODE_STYLE_DEFAULTS
loadSaveCodeStyleForm.useDefaultObsoleteCodeCheckBox.isSelected = settings.kotlinCustomSettings.OVERRIDE_PROJECT_DEFAULTS
}
override fun onSomethingChanged() {

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.kotlin.idea.formatter.LoadSaveCodeStyleForm">
<grid id="27dc6" binding="panel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="5" left="5" bottom="5" right="5"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="bb269" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="fc041" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Use defaults from:"/>
</properties>
</component>
<hspacer id="747e3">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="6a0af" class="javax.swing.JComboBox" binding="saveDefaultsComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<model/>
</properties>
</component>
</children>
</grid>
<vspacer id="e6a4d">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="de296" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="dff62" class="javax.swing.JCheckBox" binding="useDefaultObsoleteCodeCheckBox">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Use default obsolete code style for this project"/>
</properties>
</component>
<component id="37634" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Can be used only with default IDE code style without adjustments"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>

View File

@@ -0,0 +1,14 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.formatter;
import javax.swing.*;
public class LoadSaveCodeStyleForm {
public JComboBox saveDefaultsComboBox;
public JPanel panel;
public JCheckBox useDefaultObsoleteCodeCheckBox;
}