Better indent in multi-line strings (KT-17849)
Inspired by MultilineStringEnterHandler from https://github.com/JetBrains/intellij-scala https://github.com/JetBrains/intellij-scala/blob/edb741f344afff063197b406ca0c7c266a26c436/src/org/jetbrains/plugins/scala/editor/enterHandler/MultilineStringEnterHandler.scala #KT-17849 Fixed
This commit is contained in:
@@ -89,6 +89,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiled
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractCommonDecompiledTextTest
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractJsDecompiledTextFromJsMetadataTest
|
||||
import org.jetbrains.kotlin.idea.decompiler.textBuilder.AbstractJvmDecompiledTextTest
|
||||
import org.jetbrains.kotlin.idea.editor.AbstractMultiLineStringIndentTest
|
||||
import org.jetbrains.kotlin.idea.editor.backspaceHandler.AbstractBackspaceHandlerTest
|
||||
import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest
|
||||
import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest
|
||||
@@ -680,6 +681,10 @@ fun main(args: Array<String>) {
|
||||
model("editor/backspaceHandler")
|
||||
}
|
||||
|
||||
testClass<AbstractMultiLineStringIndentTest> {
|
||||
model("editor/enterHandler/multilineString")
|
||||
}
|
||||
|
||||
testClass<AbstractQuickDocProviderTest> {
|
||||
model("editor/quickDoc", pattern = """^([^_]+)\.[^\.]*$""")
|
||||
}
|
||||
|
||||
@@ -558,6 +558,8 @@
|
||||
<typedHandler implementation="org.jetbrains.kotlin.idea.kdoc.KDocTypedHandler"/>
|
||||
<enterHandlerDelegate implementation="org.jetbrains.kotlin.idea.editor.KotlinEnterHandler"
|
||||
id="KotlinEnterHandler" order="before EnterBetweenBracesHandler"/>
|
||||
<enterHandlerDelegate implementation="org.jetbrains.kotlin.idea.editor.KotlinMultilineStringEnterHandler"
|
||||
id="KotlinMultilineStringEnterHandler" order="before EnterBetweenBracesHandler"/>
|
||||
<lang.smartEnterProcessor language="kotlin" implementationClass="org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler"/>
|
||||
<backspaceHandlerDelegate implementation="org.jetbrains.kotlin.idea.editor.KotlinBackspaceHandler"/>
|
||||
<backspaceHandlerDelegate implementation="org.jetbrains.kotlin.idea.editor.KotlinStringTemplateBackspaceHandler"/>
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.idea.editor
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate.Result
|
||||
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
|
||||
private var wasInMultilineString: Boolean = false
|
||||
private var whiteSpaceAfterCaret: String = ""
|
||||
|
||||
override fun preprocessEnter(
|
||||
file: PsiFile, editor: Editor, caretOffset: Ref<Int>, caretAdvance: Ref<Int>, dataContext: DataContext,
|
||||
originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result {
|
||||
if (file !is KtFile) return Result.Continue
|
||||
|
||||
val document = editor.document
|
||||
val text = document.text
|
||||
val offset = caretOffset.get().toInt()
|
||||
|
||||
if (offset == 0 || offset >= text.length) return Result.Continue
|
||||
|
||||
val element = file.findElementAt(offset)
|
||||
if (!inMultilineString(element, offset)) {
|
||||
return Result.Continue
|
||||
}
|
||||
else {
|
||||
wasInMultilineString = true
|
||||
}
|
||||
|
||||
whiteSpaceAfterCaret = text.substring(offset).takeWhile { ch -> ch == ' ' || ch == '\t' }
|
||||
document.deleteString(offset, offset + whiteSpaceAfterCaret.length)
|
||||
|
||||
val ch1 = text[offset - 1]
|
||||
val ch2 = text[offset]
|
||||
val isInBrace = (ch1 == '(' && ch2 == ')') || (ch1 == '{' && ch2 == '}')
|
||||
if (!isInBrace || !CodeInsightSettings.getInstance().SMART_INDENT_ON_ENTER) {
|
||||
return Result.Continue
|
||||
}
|
||||
|
||||
originalHandler?.execute(editor, editor.caretModel.currentCaret, dataContext)
|
||||
return Result.DefaultForceIndent
|
||||
}
|
||||
|
||||
override fun postProcessEnter(file: PsiFile, editor: Editor, dataContext: DataContext): Result {
|
||||
if (file !is KtFile) return Result.Continue
|
||||
|
||||
if (!wasInMultilineString) return Result.Continue
|
||||
wasInMultilineString = false
|
||||
|
||||
val project = file.project
|
||||
val document = editor.document
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document)
|
||||
|
||||
val caretModel = editor.caretModel
|
||||
val offset = caretModel.offset
|
||||
|
||||
val element = file.findElementAt(offset) ?: return Result.Continue
|
||||
val literal = findString(element, offset) ?: return Result.Continue
|
||||
|
||||
val hasTrimIndentCallInChain = hasTrimIndentCallInChain(literal)
|
||||
val marginChar = if (hasTrimIndentCallInChain)
|
||||
null
|
||||
else
|
||||
getMarginCharFromTrimMarginCallsInChain(literal) ?: getMarginCharFromLiteral(literal)
|
||||
|
||||
runWriteAction {
|
||||
val settings = MultilineSettings(file.project)
|
||||
|
||||
val caretMarker = document.createRangeMarker(offset, offset)
|
||||
caretMarker.isGreedyToRight = true
|
||||
fun caretOffset(): Int = caretMarker.endOffset
|
||||
|
||||
val prevLineNumber = document.getLineNumber(offset) - 1
|
||||
assert(prevLineNumber >= 0)
|
||||
|
||||
val prevLine = getLineByNumber(prevLineNumber, document)
|
||||
val currentLine = getLineByNumber(prevLineNumber + 1, document)
|
||||
val nextLine = if (document.lineCount > prevLineNumber + 2) getLineByNumber(prevLineNumber + 2, document) else ""
|
||||
|
||||
val wasSingleLine = literal.text.indexOf("\n") == literal.text.lastIndexOf("\n") // Only one '\n' in the string after insertion
|
||||
val lines = literal.text.split("\n")
|
||||
|
||||
val inBraces = (prevLine.endsWith("{") && nextLine.trim().startsWith("}")) ||
|
||||
(prevLine.endsWith("(") && nextLine.trim().startsWith(")"))
|
||||
|
||||
val literalOffset = literal.textRange.startOffset
|
||||
if (wasSingleLine || (lines.size == 3 && inBraces)) {
|
||||
val shouldUseTrimIndent = hasTrimIndentCallInChain || (marginChar == null && lines.first().trim() == MULTILINE_QUOTE)
|
||||
val newMarginChar: Char? = if (shouldUseTrimIndent) null else (marginChar ?: DEFAULT_TRIM_MARGIN_CHAR)
|
||||
|
||||
insertTrimCall(document, literal, if (shouldUseTrimIndent) null else newMarginChar)
|
||||
|
||||
val prevIndent = settings.indentLength(prevLine)
|
||||
val indentSize = prevIndent + settings.marginIndent
|
||||
|
||||
forceIndent(caretOffset(), indentSize, newMarginChar, document, settings)
|
||||
|
||||
val isInLineEnd = literal.text.substring(offset - literalOffset) == MULTILINE_QUOTE
|
||||
if (isInLineEnd) {
|
||||
// Move close quote to next line
|
||||
caretMarker.isGreedyToRight = false
|
||||
insertNewLine(caretOffset(), prevIndent, document, settings)
|
||||
caretMarker.isGreedyToRight = true
|
||||
}
|
||||
|
||||
if (inBraces) {
|
||||
// Move closing bracket under same indent
|
||||
forceIndent(caretOffset() + 1, indentSize, newMarginChar, document, settings)
|
||||
}
|
||||
}
|
||||
else {
|
||||
val isPrevLineFirst = document.getLineNumber(literalOffset) == prevLineNumber
|
||||
|
||||
val indentInPreviousLine = when {
|
||||
isPrevLineFirst -> lines.first().substring(MULTILINE_QUOTE.length)
|
||||
else -> prevLine
|
||||
}.prefixLength { it == ' ' || it == '\t' }
|
||||
|
||||
val prefixStripped = when {
|
||||
isPrevLineFirst -> lines.first().substring(indentInPreviousLine + MULTILINE_QUOTE.length)
|
||||
else -> prevLine.substring(indentInPreviousLine)
|
||||
}
|
||||
|
||||
val nonBlankNotFirstLines = lines.subList(1, lines.size).filterNot { it.isBlank() || it.trimStart() == MULTILINE_QUOTE }
|
||||
|
||||
val marginCharToInsert = if (marginChar != null &&
|
||||
!prefixStripped.startsWith(marginChar) &&
|
||||
!nonBlankNotFirstLines.isEmpty() &&
|
||||
nonBlankNotFirstLines.none { it.trimStart().startsWith(marginChar) }) {
|
||||
|
||||
// We have margin char but decide not to insert it
|
||||
null
|
||||
}
|
||||
else {
|
||||
marginChar
|
||||
}
|
||||
|
||||
if (marginCharToInsert == null || !currentLine.trimStart().startsWith(marginCharToInsert)) {
|
||||
val indentLength = when {
|
||||
inBraces -> settings.indentLength(nextLine)
|
||||
!isPrevLineFirst -> settings.indentLength(prevLine)
|
||||
else -> settings.indentLength(prevLine) + settings.marginIndent
|
||||
}
|
||||
|
||||
forceIndent(caretOffset(), indentLength, marginCharToInsert, document, settings)
|
||||
|
||||
val wsAfterMargin = when {
|
||||
marginCharToInsert != null && prefixStripped.startsWith(marginCharToInsert) -> {
|
||||
prefixStripped.substring(1).takeWhile { it == ' ' || it == '\t' }
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
|
||||
// Insert same indent after margin char that previous line has
|
||||
document.insertString(caretOffset(), wsAfterMargin)
|
||||
|
||||
if (inBraces) {
|
||||
val nextLineOffset = document.getLineStartOffset(prevLineNumber + 2)
|
||||
forceIndent(nextLineOffset, 0, null, document, settings)
|
||||
document.insertString(nextLineOffset, (marginCharToInsert?.toString() ?: "") + wsAfterMargin)
|
||||
forceIndent(nextLineOffset, indentLength, null, document, settings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.insertString(caretOffset(), whiteSpaceAfterCaret)
|
||||
|
||||
caretModel.moveToOffset(caretOffset())
|
||||
caretMarker.dispose()
|
||||
}
|
||||
|
||||
return Result.Stop
|
||||
}
|
||||
|
||||
companion object {
|
||||
val DEFAULT_TRIM_MARGIN_CHAR = '|'
|
||||
val TRIM_INDENT_CALL = "trimIndent"
|
||||
val TRIM_MARGIN_CALL = "trimMargin"
|
||||
|
||||
val MULTILINE_QUOTE = "\"\"\""
|
||||
|
||||
class MultilineSettings(project: Project) {
|
||||
private val kotlinIndentOptions =
|
||||
CodeStyleSettingsManager.getInstance(project).currentSettings.getIndentOptions(KotlinFileType.INSTANCE)
|
||||
|
||||
val useTabs = kotlinIndentOptions.USE_TAB_CHARACTER
|
||||
val tabSize = kotlinIndentOptions.TAB_SIZE
|
||||
val regularIndent = kotlinIndentOptions.INDENT_SIZE
|
||||
val marginIndent = regularIndent
|
||||
|
||||
fun getSmartSpaces(count: Int): String = when {
|
||||
useTabs -> StringUtil.repeat("\t", count / tabSize) + StringUtil.repeat(" ", count % tabSize)
|
||||
else -> StringUtil.repeat(" ", count)
|
||||
}
|
||||
|
||||
fun indentLength(line: String): Int = when {
|
||||
useTabs -> {
|
||||
val tabsCount = line.prefixLength { it == '\t' }
|
||||
tabsCount * tabSize + line.substring(tabsCount).prefixLength { it == ' ' }
|
||||
}
|
||||
else -> line.prefixLength { it == ' ' }
|
||||
}
|
||||
}
|
||||
|
||||
fun findString(element: PsiElement?, offset: Int): KtStringTemplateExpression? {
|
||||
if (element !is LeafPsiElement) return null
|
||||
|
||||
when (element.elementType) {
|
||||
KtTokens.REGULAR_STRING_PART -> {
|
||||
// Ok
|
||||
}
|
||||
KtTokens.CLOSING_QUOTE -> {
|
||||
if (element.startOffset != offset) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
|
||||
return element.parents.firstIsInstanceOrNull<KtStringTemplateExpression>()
|
||||
}
|
||||
|
||||
fun inMultilineString(element: PsiElement?, offset: Int) =
|
||||
!(findString(element, offset)?.isSingleQuoted() ?: true)
|
||||
|
||||
fun getMarginCharFromLiteral(str: KtStringTemplateExpression, marginChar: Char = DEFAULT_TRIM_MARGIN_CHAR): Char? {
|
||||
val lines = str.text.lines()
|
||||
if (lines.size <= 2) return null
|
||||
|
||||
val middleNonBlank = lines.subList(1, lines.size - 1).filter { !it.isBlank() }
|
||||
|
||||
if (middleNonBlank.isNotEmpty() && middleNonBlank.all { it.trimStart().startsWith(marginChar) }) {
|
||||
return marginChar
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
fun getLiteralCalls(str: KtStringTemplateExpression): Sequence<KtCallExpression> {
|
||||
var previous: PsiElement = str
|
||||
return str.parents
|
||||
.takeWhile { parent ->
|
||||
if (parent is KtQualifiedExpression && parent.receiverExpression == previous) {
|
||||
previous = parent
|
||||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}
|
||||
.mapNotNull { qualified ->
|
||||
(qualified as KtQualifiedExpression).selectorExpression as? KtCallExpression
|
||||
}
|
||||
}
|
||||
|
||||
fun getMarginCharFromTrimMarginCallsInChain(str: KtStringTemplateExpression): Char? {
|
||||
val literalCall = getLiteralCalls(str).firstOrNull { call ->
|
||||
call.getCallNameExpression()?.text == TRIM_MARGIN_CALL
|
||||
} ?: return null
|
||||
|
||||
val firstArgument = literalCall.valueArguments.getOrNull(0) ?: return DEFAULT_TRIM_MARGIN_CHAR
|
||||
val argumentExpression = firstArgument.getArgumentExpression() as? KtStringTemplateExpression ?: return DEFAULT_TRIM_MARGIN_CHAR
|
||||
val entry = argumentExpression.entries.singleOrNull() as? KtLiteralStringTemplateEntry ?: return DEFAULT_TRIM_MARGIN_CHAR
|
||||
|
||||
return entry.text?.singleOrNull() ?: DEFAULT_TRIM_MARGIN_CHAR
|
||||
}
|
||||
|
||||
fun hasTrimIndentCallInChain(str: KtStringTemplateExpression): Boolean {
|
||||
return getLiteralCalls(str).any { call -> call.getCallNameExpression()?.text == TRIM_INDENT_CALL }
|
||||
}
|
||||
|
||||
fun getLineByNumber(number: Int, document: Document): String =
|
||||
document.getText(TextRange(document.getLineStartOffset(number), document.getLineEndOffset(number)))
|
||||
|
||||
fun insertNewLine(nlOffset: Int, indent: Int, document: Document, settings: MultilineSettings) {
|
||||
document.insertString(nlOffset, "\n")
|
||||
forceIndent(nlOffset + 1, indent, null, document, settings)
|
||||
}
|
||||
|
||||
fun forceIndent(offset: Int, indent: Int, marginChar: Char?, document: Document, settings: MultilineSettings) {
|
||||
val lineNumber = document.getLineNumber(offset)
|
||||
val lineStart = document.getLineStartOffset(lineNumber)
|
||||
val line = getLineByNumber(lineNumber, document)
|
||||
val wsPrefix = line.takeWhile { c -> c == ' ' || c == '\t' }
|
||||
document.replaceString(lineStart,
|
||||
lineStart + wsPrefix.length,
|
||||
settings.getSmartSpaces(indent) + (marginChar?.toString() ?: ""))
|
||||
}
|
||||
|
||||
fun String.prefixLength(f: (Char) -> Boolean) = takeWhile(f).count()
|
||||
|
||||
fun insertTrimCall(document: Document, literal: KtStringTemplateExpression, marginChar: Char?) {
|
||||
if (hasTrimIndentCallInChain(literal) || getMarginCharFromTrimMarginCallsInChain(literal) != null) return
|
||||
if (literal.parents.any { it is KtAnnotationEntry }) return
|
||||
|
||||
if (marginChar == null) {
|
||||
document.insertString(literal.textRange.endOffset, ".$TRIM_INDENT_CALL()")
|
||||
}
|
||||
else {
|
||||
document.insertString(
|
||||
literal.textRange.endOffset,
|
||||
if (marginChar == DEFAULT_TRIM_MARGIN_CHAR) {
|
||||
".$TRIM_MARGIN_CALL()"
|
||||
}
|
||||
else {
|
||||
".$TRIM_MARGIN_CALL(\"$marginChar\")"
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
val a =
|
||||
"""bl<caret>ah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""bl
|
||||
<caret>ah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
""".trimMargin()
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah<caret>
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
<caret>
|
||||
""".trimMargin()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
<caret>
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
|
||||
<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
<caret>
|
||||
"""
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
val a =
|
||||
"""bl<caret>ah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
"""
|
||||
//-----
|
||||
val a =
|
||||
"""bl
|
||||
<caret>ah blah blah
|
||||
blah blah blah
|
||||
blah blah blah
|
||||
"""
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".trimMargin()
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah blah<caret>""".replace(" ", "")?.replace("b", "p").trimMargin().length
|
||||
//-----
|
||||
val a = """blah blah blah
|
||||
|<caret>
|
||||
""".replace(" ", "")?.replace("b", "p").trimMargin().length
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
val a =
|
||||
("""
|
||||
| blah blah
|
||||
| blah blah
|
||||
""" + """<caret>""").trimMargin()
|
||||
|
||||
// TODO: Concatenation is not supported
|
||||
//-----
|
||||
val a =
|
||||
("""
|
||||
| blah blah
|
||||
| blah blah
|
||||
""" + """
|
||||
<caret>
|
||||
""".trimIndent()).trimMargin()
|
||||
|
||||
// TODO: Concatenation is not supported
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah blah<caret>""".replace(" ", "")?.replace("b", "p").trimIndent().length
|
||||
//-----
|
||||
val a = """blah blah blah
|
||||
<caret>
|
||||
""".replace(" ", "")?.replace("b", "p").trimIndent().length
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fun some() {
|
||||
val b = """
|
||||
|helle<caret>|asdf
|
||||
""".trimMargin()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
|helle
|
||||
<caret>|asdf
|
||||
""".trimMargin()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
val a =
|
||||
"""blah blah
|
||||
| blah blah
|
||||
| blah blah""" + """blah blah<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""blah blah
|
||||
| blah blah
|
||||
| blah blah""" + """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
fun main(args: Array<String>) {
|
||||
println("""
|
||||
<caret>
|
||||
| sdf""".trimMargin())
|
||||
}
|
||||
//-----
|
||||
fun main(args: Array<String>) {
|
||||
println("""
|
||||
|
||||
|<caret>
|
||||
| sdf""".trimMargin())
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".replace("\r", "")
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin().replace("\r", "")
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
val a = """ <caret>blah blah"""
|
||||
//-----
|
||||
val a = """
|
||||
<caret>blah blah""".trimIndent()
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
fun some() {
|
||||
val b = """<caret>
|
||||
"""
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
<caret>
|
||||
"""
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah {<caret>}
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah {
|
||||
| <caret>
|
||||
| }
|
||||
""".trimMargin()
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fun some() {
|
||||
val b = """
|
||||
class Test {
|
||||
fun some() {<caret>}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
class Test {
|
||||
fun some() {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
fun some() {
|
||||
val b = """class Test {<caret>}"""
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """class Test {
|
||||
|<caret>
|
||||
|}""".trimMargin()
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
object A {
|
||||
val a = """blah<caret> blah"""
|
||||
}
|
||||
//-----
|
||||
object A {
|
||||
val a = """blah
|
||||
| <caret>blah""".trimMargin()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| <caret>
|
||||
"""
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
val a = """blah blah blah
|
||||
| blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a = """blah blah blah
|
||||
| blah blah
|
||||
| <caret>
|
||||
"""
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
fun some() {
|
||||
val b = """<caret>
|
||||
""".trimMargin()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fun some() {
|
||||
val b = """<caret>
|
||||
|hello
|
||||
""".trimMargin()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
|<caret>
|
||||
|hello
|
||||
""".trimMargin()
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
fun some() {
|
||||
val b = """abc<caret>
|
||||
""".trimMargin()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """abc
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
val a = """<caret>"""
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val a = """
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>"""
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""blah blah<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
val a = """blah blah<caret>""".trimMargin("#")
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val a = """blah blah
|
||||
#<caret>
|
||||
""".trimMargin("#")
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class A {
|
||||
val a = """<caret>blah blah""".trimMargin("#")
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val a = """
|
||||
#<caret>blah blah""".trimMargin("#")
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
val m = '#'
|
||||
val a = """blah blah<caret>""".trimMargin(m)
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val m = '#'
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin(m)
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
@Annotation("""<caret>""")
|
||||
fun some() {}
|
||||
//-----
|
||||
@Annotation("""
|
||||
<caret>
|
||||
""")
|
||||
fun some() {}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
fun main(args: Array<String>) {
|
||||
println("""
|
||||
<caret>
|
||||
| sdf""".trimMargin())
|
||||
}
|
||||
//-----
|
||||
fun main(args: Array<String>) {
|
||||
println("""
|
||||
|
||||
|<caret>
|
||||
| sdf""".trimMargin())
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".trimMargin()
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".replace("\r", "")
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin().replace("\r", "")
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
fun some() {
|
||||
val b = """<caret>
|
||||
"""
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
<caret>
|
||||
"""
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah {<caret>}
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah {
|
||||
| <caret>
|
||||
| }
|
||||
""".trimMargin()
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
object A {
|
||||
val a = """blah<caret> blah"""
|
||||
}
|
||||
//-----
|
||||
object A {
|
||||
val a = """blah
|
||||
| <caret>blah""".trimMargin()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| <caret>
|
||||
"""
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
val a = """blah blah blah
|
||||
| blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a = """blah blah blah
|
||||
| blah blah
|
||||
| <caret>
|
||||
"""
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
val a = """<caret>"""
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val a = """
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>"""
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""blah blah<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
@@ -0,0 +1,3 @@
|
||||
// SET_TRUE: USE_TAB_CHARACTER
|
||||
// SET_INT: TAB_SIZE=2
|
||||
// SET_INT: INDENT_SIZE=2
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".trimMargin()
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>""".replace("\r", "")
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin().replace("\r", "")
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah {<caret>}
|
||||
""".trimMargin()
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah {
|
||||
| <caret>
|
||||
| }
|
||||
""".trimMargin()
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
object A {
|
||||
val a = """blah<caret> blah"""
|
||||
}
|
||||
//-----
|
||||
object A {
|
||||
val a = """blah
|
||||
| <caret>blah""".trimMargin()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| blah blah blah
|
||||
| <caret>
|
||||
"""
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
val a = """blah blah blah
|
||||
| blah blah<caret>
|
||||
"""
|
||||
//-----
|
||||
val a = """blah blah blah
|
||||
| blah blah
|
||||
| <caret>
|
||||
"""
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
val a = """<caret>"""
|
||||
}
|
||||
//-----
|
||||
class A {
|
||||
val a = """
|
||||
<caret>
|
||||
""".trimIndent()
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
fun some() {
|
||||
val b = """
|
||||
|class Test() {
|
||||
| fun test() {<caret>
|
||||
|}
|
||||
""".trimMargin()
|
||||
}
|
||||
//-----
|
||||
fun some() {
|
||||
val b = """
|
||||
|class Test() {
|
||||
| fun test() {
|
||||
| <caret>
|
||||
|}
|
||||
""".trimMargin()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val a = """blah blah<caret>"""
|
||||
//-----
|
||||
val a = """blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
val a =
|
||||
"""blah blah<caret>"""
|
||||
//-----
|
||||
val a =
|
||||
"""blah blah
|
||||
|<caret>
|
||||
""".trimMargin()
|
||||
@@ -0,0 +1,3 @@
|
||||
// SET_TRUE: USE_TAB_CHARACTER
|
||||
// SET_INT: TAB_SIZE=4
|
||||
// SET_INT: INDENT_SIZE=4
|
||||
@@ -698,6 +698,39 @@ public class FormatterTestGenerated extends AbstractFormatterTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/formatter/constructor")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Constructor extends AbstractFormatterTest {
|
||||
public void testAllFilesPresentInConstructor() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/formatter/constructor"), Pattern.compile("^([^\\.]+)\\.after\\.kt.*$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterListChopAsNeeded.after.kt")
|
||||
public void testParameterListChopAsNeeded() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/constructor/ParameterListChopAsNeeded.after.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterListDoNotWrap.after.kt")
|
||||
public void testParameterListDoNotWrap() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/constructor/ParameterListDoNotWrap.after.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterListWrapAlways.after.kt")
|
||||
public void testParameterListWrapAlways() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/constructor/ParameterListWrapAlways.after.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ParameterListWrapAsNeeded.after.kt")
|
||||
public void testParameterListWrapAsNeeded() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/formatter/constructor/ParameterListWrapAsNeeded.after.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/formatter/fileAnnotations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.idea.editor
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import com.intellij.testFramework.EditorTestUtil
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.SettingsConfigurator
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractMultiLineStringIndentTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
val FILE_SEPARATOR = "//-----"
|
||||
|
||||
protected fun doTest(path: String) {
|
||||
val testDir = File(path).parentFile
|
||||
val settingsFile = File(testDir, "settings.txt")
|
||||
|
||||
setupSettings(settingsFile) {
|
||||
val multiFileText = FileUtil.loadFile(File(path), true)
|
||||
|
||||
val beforeFile = multiFileText.substringBefore(FILE_SEPARATOR).trim()
|
||||
val afterFile = multiFileText.substringAfter(FILE_SEPARATOR).trim()
|
||||
|
||||
myFixture.configureByText(KotlinFileType.INSTANCE, beforeFile)
|
||||
myFixture.type('\n')
|
||||
|
||||
val caretModel = myFixture.editor.caretModel
|
||||
val offset = caretModel.offset
|
||||
val actualTextWithCaret = StringBuilder(myFixture.editor.document.text).insert(offset, EditorTestUtil.CARET_TAG).toString()
|
||||
|
||||
if (afterFile != actualTextWithCaret) {
|
||||
KotlinTestUtils.assertEqualsToFile(File(path), "$beforeFile\n$FILE_SEPARATOR\n$actualTextWithCaret")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setupSettings(settingsFile: File, inverted: Boolean = false, action: () -> Unit) {
|
||||
if (!settingsFile.exists()) {
|
||||
// Don nothing with settings
|
||||
action()
|
||||
return
|
||||
}
|
||||
|
||||
val settingsFileText = FileUtil.loadFile(settingsFile, true)
|
||||
try {
|
||||
val indentOptions = CodeStyleSettingsManager.getInstance(project).currentSettings.getIndentOptions(KotlinFileType.INSTANCE)
|
||||
val configurator = SettingsConfigurator(settingsFileText, indentOptions)
|
||||
if (!inverted) {
|
||||
configurator.configureSettings()
|
||||
}
|
||||
else {
|
||||
configurator.configureInvertedSettings()
|
||||
}
|
||||
|
||||
action()
|
||||
}
|
||||
finally {
|
||||
CodeStyleSettingsManager.getSettings(myFixture.project).clearCodeStyleSettings()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getProjectDescriptor() = JAVA_LATEST!!
|
||||
override fun getTestDataPath(): String = ""
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* 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 org.jetbrains.kotlin.idea.editor;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/editor/enterHandler/multilineString")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class MultiLineStringIndentTestGenerated extends AbstractMultiLineStringIndentTest {
|
||||
public void testAllFilesPresentInMultilineString() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/enterHandler/multilineString"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/editor/enterHandler/multilineString/spaces")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Spaces extends AbstractMultiLineStringIndentTest {
|
||||
public void testAllFilesPresentInSpaces() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/enterHandler/multilineString/spaces"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("dontAddMarginCharWhenMultilineWithoutMargins.kt")
|
||||
public void testDontAddMarginCharWhenMultilineWithoutMargins() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontAddMarginCharWhenMultilineWithoutMargins.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontAddMarginWhenItIsUnused.kt")
|
||||
public void testDontAddMarginWhenItIsUnused() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontAddMarginWhenItIsUnused.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontAddMarginWhenItIsUnusedWithEmptyPrevious.kt")
|
||||
public void testDontAddMarginWhenItIsUnusedWithEmptyPrevious() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontAddMarginWhenItIsUnusedWithEmptyPrevious.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontAddTrimCallWhenAlreadyMultiline.kt")
|
||||
public void testDontAddTrimCallWhenAlreadyMultiline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontAddTrimCallWhenAlreadyMultiline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontAddTrimCallWhenAlreadyMultilineFirstLine.kt")
|
||||
public void testDontAddTrimCallWhenAlreadyMultilineFirstLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontAddTrimCallWhenAlreadyMultilineFirstLine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMargin1.kt")
|
||||
public void testDontInsertTrimMargin1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontInsertTrimMargin1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMargin2.kt")
|
||||
public void testDontInsertTrimMargin2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontInsertTrimMargin2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMargin3.kt")
|
||||
public void testDontInsertTrimMargin3() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontInsertTrimMargin3.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMargin4.kt")
|
||||
public void testDontInsertTrimMargin4() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/dontInsertTrimMargin4.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterBeforeMarginChar.kt")
|
||||
public void testEnterBeforeMarginChar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterBeforeMarginChar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInInfixMargin.kt")
|
||||
public void testEnterInInfixMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInInfixMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInLineWithMarginOnNotMargedLine.kt")
|
||||
public void testEnterInLineWithMarginOnNotMargedLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInLineWithMarginOnNotMargedLine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInMethodCallMargin.kt")
|
||||
public void testEnterInMethodCallMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInMethodCallMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInOneLineAfterSpaces.kt")
|
||||
public void testEnterInOneLineAfterSpaces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInOneLineAfterSpaces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInTwoLinesNoMarginCall.kt")
|
||||
public void testEnterInTwoLinesNoMarginCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInTwoLinesNoMarginCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideBraces.kt")
|
||||
public void testEnterInsideBraces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInsideBraces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideBraces1.kt")
|
||||
public void testEnterInsideBraces1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInsideBraces1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideBraces2.kt")
|
||||
public void testEnterInsideBraces2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInsideBraces2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideTextMargin.kt")
|
||||
public void testEnterInsideTextMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterInsideTextMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLSimpleMargin.kt")
|
||||
public void testEnterMLSimpleMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterMLSimpleMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLStartOnSameLineMargin.kt")
|
||||
public void testEnterMLStartOnSameLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterMLStartOnSameLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnFirstLineWithPresentTrimMargin.kt")
|
||||
public void testEnterOnFirstLineWithPresentTrimMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterOnFirstLineWithPresentTrimMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnFirstLineWithPresentTrimMarginAndLine.kt")
|
||||
public void testEnterOnFirstLineWithPresentTrimMarginAndLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterOnFirstLineWithPresentTrimMarginAndLine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnFirstNonEmptyLineWithPresentTrimMargin.kt")
|
||||
public void testEnterOnFirstNonEmptyLineWithPresentTrimMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterOnFirstNonEmptyLineWithPresentTrimMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnNewLine.kt")
|
||||
public void testEnterOnNewLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterOnNewLine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterSimple.kt")
|
||||
public void testEnterSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterSimple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextMargin.kt")
|
||||
public void testEnterWithTextMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterWithTextMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextOnNewLineMargin.kt")
|
||||
public void testEnterWithTextOnNewLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/enterWithTextOnNewLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("insertCustomMargin.kt")
|
||||
public void testInsertCustomMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/insertCustomMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("insertCustomMarginInLineStart.kt")
|
||||
public void testInsertCustomMarginInLineStart() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/insertCustomMarginInLineStart.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("insertDefaultMargin.kt")
|
||||
public void testInsertDefaultMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/insertDefaultMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noTrimIndentInAnnotations.kt")
|
||||
public void testNoTrimIndentInAnnotations() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/noTrimIndentInAnnotations.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("restoreIndentFromEmptyLine.kt")
|
||||
public void testRestoreIndentFromEmptyLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/spaces/restoreIndentFromEmptyLine.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/editor/enterHandler/multilineString/withTabs")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class WithTabs extends AbstractMultiLineStringIndentTest {
|
||||
public void testAllFilesPresentInWithTabs() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/enterHandler/multilineString/withTabs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Tabs2 extends AbstractMultiLineStringIndentTest {
|
||||
public void testAllFilesPresentInTabs2() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMarginCall.kt")
|
||||
public void testDontInsertTrimMarginCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/dontInsertTrimMarginCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInMethodCallMargin.kt")
|
||||
public void testEnterInMethodCallMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterInMethodCallMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInTwoLinesNoMarginCall.kt")
|
||||
public void testEnterInTwoLinesNoMarginCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterInTwoLinesNoMarginCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideBraces.kt")
|
||||
public void testEnterInsideBraces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterInsideBraces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideText.kt")
|
||||
public void testEnterInsideText() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterInsideText.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLSimpleMargin.kt")
|
||||
public void testEnterMLSimpleMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterMLSimpleMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLStartOnSameLineMargin.kt")
|
||||
public void testEnterMLStartOnSameLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterMLStartOnSameLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnNewLineMargin.kt")
|
||||
public void testEnterOnNewLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterOnNewLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterSimpleMargin.kt")
|
||||
public void testEnterSimpleMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterSimpleMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextMargin.kt")
|
||||
public void testEnterWithTextMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterWithTextMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextOnNewLineMargin.kt")
|
||||
public void testEnterWithTextOnNewLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs2/enterWithTextOnNewLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Tabs4 extends AbstractMultiLineStringIndentTest {
|
||||
public void testAllFilesPresentInTabs4() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("dontInsertTrimMarginCall.kt")
|
||||
public void testDontInsertTrimMarginCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/dontInsertTrimMarginCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInMethodCallMargin.kt")
|
||||
public void testEnterInMethodCallMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterInMethodCallMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideBraces.kt")
|
||||
public void testEnterInsideBraces() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterInsideBraces.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterInsideText.kt")
|
||||
public void testEnterInsideText() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterInsideText.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLSimpleMargin.kt")
|
||||
public void testEnterMLSimpleMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterMLSimpleMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterMLStartOnSameLineMargin.kt")
|
||||
public void testEnterMLStartOnSameLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterMLStartOnSameLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterOnNewLineMargin.kt")
|
||||
public void testEnterOnNewLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterOnNewLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterSimpleMargin.kt")
|
||||
public void testEnterSimpleMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterSimpleMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTabsAfterMarginChar.kt")
|
||||
public void testEnterWithTabsAfterMarginChar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterWithTabsAfterMarginChar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextMargin.kt")
|
||||
public void testEnterWithTextMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterWithTextMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enterWithTextOnNewLineMargin.kt")
|
||||
public void testEnterWithTextOnNewLineMargin() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/editor/enterHandler/multilineString/withTabs/tabs4/enterWithTextOnNewLineMargin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -384,12 +384,6 @@ class TypedHandlerTest : LightCodeInsightTestCase() {
|
||||
" \"bar\").length()"
|
||||
)
|
||||
|
||||
fun testSplitStringByEnter_TripleQuotedString(): Unit = doCharTypeTest(
|
||||
'\n',
|
||||
"val l = \"\"\"foo<caret>bar\"\"\"",
|
||||
"val l = \"\"\"foo\nbar\"\"\""
|
||||
)
|
||||
|
||||
fun testTypeLtInFunDeclaration() {
|
||||
doLtGtTest("fun <caret>")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user