Reformat in idea.editor package

This commit is contained in:
Nikolay Krasko
2018-12-06 18:17:07 +03:00
parent c85f56a0a8
commit 05269cea2f
28 changed files with 180 additions and 177 deletions
@@ -60,14 +60,14 @@ class BatchTemplateRunner(private val project: Project) {
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document) PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.document)
val template = factory() ?: return@executeWriteCommand val template = factory() ?: return@executeWriteCommand
manager.startTemplate( manager.startTemplate(
editor, editor,
template, template,
object : TemplateEditingAdapter() { object : TemplateEditingAdapter() {
override fun templateFinished(template: Template, brokenOff: Boolean) { override fun templateFinished(template: Template, brokenOff: Boolean) {
if (brokenOff) return if (brokenOff) return
ApplicationManager.getApplication().invokeLater { runTemplates(iterator) } ApplicationManager.getApplication().invokeLater { runTemplates(iterator) }
}
} }
}
) )
} }
} }
@@ -30,7 +30,7 @@ public class KotlinBackspaceHandler extends BackspaceHandlerDelegate {
@Override @Override
public void beforeCharDeleted(char c, PsiFile file, Editor editor) { public void beforeCharDeleted(char c, PsiFile file, Editor editor) {
int offset = editor.getCaretModel().getOffset() - 1; int offset = editor.getCaretModel().getOffset() - 1;
deleteGt = c =='<' && file instanceof KtFile && deleteGt = c == '<' && file instanceof KtFile &&
(isAfterToken(offset, editor, KtTokens.FUN_KEYWORD) || (isAfterToken(offset, editor, KtTokens.FUN_KEYWORD) ||
isAfterToken(offset, editor, KtTokens.IDENTIFIER)); isAfterToken(offset, editor, KtTokens.IDENTIFIER));
} }
@@ -70,7 +70,8 @@ public class KotlinEditorOptions implements PersistentStateComponent<KotlinEdito
public Object clone() { public Object clone() {
try { try {
return super.clone(); return super.clone();
} catch (CloneNotSupportedException e) { }
catch (CloneNotSupportedException e) {
return null; return null;
} }
} }
@@ -30,19 +30,19 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted import org.jetbrains.kotlin.psi.psiUtil.isSingleQuoted
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
class KotlinEnterHandler: EnterHandlerDelegateAdapter() { class KotlinEnterHandler : EnterHandlerDelegateAdapter() {
companion object { companion object {
private val LOG = Logger.getInstance(KotlinEnterHandler::class.java) private val LOG = Logger.getInstance(KotlinEnterHandler::class.java)
private val FORCE_INDENT_IN_LAMBDA_AFTER = TokenSet.create(KtTokens.ARROW, KtTokens.LBRACE) private val FORCE_INDENT_IN_LAMBDA_AFTER = TokenSet.create(KtTokens.ARROW, KtTokens.LBRACE)
} }
override fun preprocessEnter( override fun preprocessEnter(
file: PsiFile, file: PsiFile,
editor: Editor, editor: Editor,
caretOffsetRef: Ref<Int>, caretOffsetRef: Ref<Int>,
caretAdvance: Ref<Int>, caretAdvance: Ref<Int>,
dataContext: DataContext, dataContext: DataContext,
originalHandler: EditorActionHandler? originalHandler: EditorActionHandler?
): EnterHandlerDelegate.Result? { ): EnterHandlerDelegate.Result? {
if (file !is KtFile) return EnterHandlerDelegate.Result.Continue if (file !is KtFile) return EnterHandlerDelegate.Result.Continue
@@ -74,8 +74,7 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() {
try { try {
CodeStyleManager.getInstance(file.getProject())!!.adjustLineIndent(file, editor.caretModel.offset) CodeStyleManager.getInstance(file.getProject())!!.adjustLineIndent(file, editor.caretModel.offset)
} } catch (e: IncorrectOperationException) {
catch (e: IncorrectOperationException) {
LOG.error(e) LOG.error(e)
} }
@@ -88,10 +87,12 @@ class KotlinEnterHandler: EnterHandlerDelegateAdapter() {
// We can't use the core platform logic (EnterInStringLiteralHandler) because it assumes that the string // We can't use the core platform logic (EnterInStringLiteralHandler) because it assumes that the string
// is a single token and the first character of the token is an opening quote. In the case of Kotlin, // is a single token and the first character of the token is an opening quote. In the case of Kotlin,
// the opening quote is a separate token and the first character of the string token is just a random letter. // the opening quote is a separate token and the first character of the string token is just a random letter.
private fun preprocessEnterInStringLiteral(psiFile: PsiFile, private fun preprocessEnterInStringLiteral(
editor: Editor, psiFile: PsiFile,
caretOffsetRef: Ref<Int>, editor: Editor,
caretAdvanceRef: Ref<Int>): Boolean { caretOffsetRef: Ref<Int>,
caretAdvanceRef: Ref<Int>
): Boolean {
var caretOffset = caretOffsetRef.get() var caretOffset = caretOffsetRef.get()
val psiAtOffset = psiFile.findElementAt(caretOffset) ?: return false val psiAtOffset = psiFile.findElementAt(caretOffset) ?: return false
val stringTemplate = psiAtOffset.getStrictParentOfType<KtStringTemplateExpression>() ?: return false val stringTemplate = psiAtOffset.getStrictParentOfType<KtStringTemplateExpression>() ?: return false
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.psi.psiUtil.*
private val PsiElement.templateContentRange: TextRange? private val PsiElement.templateContentRange: TextRange?
get() = this.getParentOfType<KtStringTemplateExpression>(false)?.let{ get() = this.getParentOfType<KtStringTemplateExpression>(false)?.let {
it.textRange.cutOut(it.getContentRange()) it.textRange.cutOut(it.getContentRange())
} }
@@ -61,8 +61,7 @@ private fun deduceBlockSelectionWidth(startOffsets: IntArray, endOffsets: IntArr
} }
return if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) { return if (totalLength < text.length && (text.length + 1) % fragmentCount == 0) {
(text.length + 1) / fragmentCount - 1 (text.length + 1) / fragmentCount - 1
} } else {
else {
-1 -1
} }
} }
@@ -91,20 +90,19 @@ class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor {
} }
val elTp = element.node.elementType val elTp = element.node.elementType
if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) && if (elTp == KtTokens.ESCAPE_SEQUENCE && fileRange.contains(element.range) &&
element.templateContentRange?.contains(fileRange) == true) { element.templateContentRange?.contains(fileRange) == true
) {
val tpEntry = element.parent as KtEscapeStringTemplateEntry val tpEntry = element.parent as KtEscapeStringTemplateEntry
changed = true changed = true
buffer.append(tpEntry.unescapedValue) buffer.append(tpEntry.unescapedValue)
givenTextOffset = element.endOffset givenTextOffset = element.endOffset
} } else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) {
else if (elTp == KtTokens.SHORT_TEMPLATE_ENTRY_START || elTp == KtTokens.LONG_TEMPLATE_ENTRY_START) {
//Process inner templates without escaping //Process inner templates without escaping
val tpEntry = element.parent val tpEntry = element.parent
val inter = fileRange.intersection(tpEntry.range)!! val inter = fileRange.intersection(tpEntry.range)!!
buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) buffer.append(fileText.substring(inter.startOffset, inter.endOffset))
givenTextOffset = inter.endOffset givenTextOffset = inter.endOffset
} } else {
else {
val inter = fileRange.intersection(element.range)!! val inter = fileRange.intersection(element.range)!!
buffer.append(fileText.substring(inter.startOffset, inter.endOffset)) buffer.append(fileText.substring(inter.startOffset, inter.endOffset))
givenTextOffset = inter.endOffset givenTextOffset = inter.endOffset
@@ -143,13 +141,12 @@ class KotlinLiteralCopyPasteProcessor : CopyPastePreProcessor {
} }
endsInLineBreak = it is NewLineChunk endsInLineBreak = it is NewLineChunk
} }
return if (endsInLineBreak){ return if (endsInLineBreak) {
res.removeSuffix(lineBreak).toString() + "\\n" res.removeSuffix(lineBreak).toString() + "\\n"
} else{ } else {
res.toString() res.toString()
} }
} } else {
else {
val tripleQuoteRe = Regex("[\"]{3,}") val tripleQuoteRe = Regex("[\"]{3,}")
TemplateTokenSequence(text).map { chunk -> TemplateTokenSequence(text).map { chunk ->
when (chunk) { when (chunk) {
@@ -172,13 +169,11 @@ private object NewLineChunk : TemplateChunk()
private class TemplateTokenSequence(private val inputString: String) : Sequence<TemplateChunk> { private class TemplateTokenSequence(private val inputString: String) : Sequence<TemplateChunk> {
private fun String.guessIsTemplateEntryStart(): Boolean = if (this.startsWith("\${")) { private fun String.guessIsTemplateEntryStart(): Boolean = if (this.startsWith("\${")) {
true true
} } else if (this.length > 1 && this[0] == '$') {
else if (this.length > 1 && this[0] == '$') {
val guessedIdentifier = substring(1) val guessedIdentifier = substring(1)
val tokenType = KotlinLexer().apply { start(guessedIdentifier) }.tokenType val tokenType = KotlinLexer().apply { start(guessedIdentifier) }.tokenType
tokenType == KtTokens.IDENTIFIER || tokenType == KtTokens.THIS_KEYWORD tokenType == KtTokens.IDENTIFIER || tokenType == KtTokens.THIS_KEYWORD
} } else {
else {
false false
} }
@@ -192,8 +187,7 @@ private class TemplateTokenSequence(private val inputString: String) : Sequence<
val tokenType = lexer.tokenType val tokenType = lexer.tokenType
return if (tokenType == KtTokens.IDENTIFIER || tokenType == KtTokens.THIS_KEYWORD) { return if (tokenType == KtTokens.IDENTIFIER || tokenType == KtTokens.THIS_KEYWORD) {
from + lexer.tokenEnd - 1 from + lexer.tokenEnd - 1
} } else {
else {
-1 -1
} }
} }
@@ -202,8 +196,7 @@ private class TemplateTokenSequence(private val inputString: String) : Sequence<
while (lexer.tokenType != null) { while (lexer.tokenType != null) {
if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) { if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START) {
depth++ depth++
} } else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) {
else if (lexer.tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END) {
depth-- depth--
if (depth == 0) { if (depth == 0) {
return from + lexer.currentPosition.offset return from + lexer.currentPosition.offset
@@ -240,16 +233,14 @@ private class TemplateTokenSequence(private val inputString: String) : Sequence<
to += 1 to += 1
if (to < inputString.length) to += 1 if (to < inputString.length) to += 1
continue continue
} } else if (c == '$') {
else if (c == '$') {
if (inputString.substring(to).guessIsTemplateEntryStart()) { if (inputString.substring(to).guessIsTemplateEntryStart()) {
if (from < to) yieldLiteral(inputString.substring(from until to)) if (from < to) yieldLiteral(inputString.substring(from until to))
from = to from = to
to = findTemplateEntryEnd(inputString, from) to = findTemplateEntryEnd(inputString, from)
if (to != -1) { if (to != -1) {
yield(EntryChunk(inputString.substring(from until to))) yield(EntryChunk(inputString.substring(from until to)))
} } else {
else {
to = inputString.length to = inputString.length
yieldLiteral(inputString.substring(from until to)) yieldLiteral(inputString.substring(from until to))
} }
@@ -53,8 +53,9 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
private var isInBrace = false private var isInBrace = false
override fun preprocessEnter( override fun preprocessEnter(
file: PsiFile, editor: Editor, caretOffset: Ref<Int>, caretAdvance: Ref<Int>, dataContext: DataContext, file: PsiFile, editor: Editor, caretOffset: Ref<Int>, caretAdvance: Ref<Int>, dataContext: DataContext,
originalHandler: EditorActionHandler?): EnterHandlerDelegate.Result { originalHandler: EditorActionHandler?
): EnterHandlerDelegate.Result {
val offset = caretOffset.get().toInt() val offset = caretOffset.get().toInt()
if (editor !is EditorWindow) { if (editor !is EditorWindow) {
return preprocessEnter(file, editor, offset, originalHandler, dataContext) return preprocessEnter(file, editor, offset, originalHandler, dataContext)
@@ -69,7 +70,13 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
return preprocessEnter(file, editor, offset, originalHandler, dataContext) return preprocessEnter(file, editor, offset, originalHandler, dataContext)
} }
private fun preprocessEnter(file: PsiFile, editor: Editor, offset: Int, originalHandler: EditorActionHandler?, dataContext: DataContext): Result { private fun preprocessEnter(
file: PsiFile,
editor: Editor,
offset: Int,
originalHandler: EditorActionHandler?,
dataContext: DataContext
): Result {
if (file !is KtFile) return Result.Continue if (file !is KtFile) return Result.Continue
val document = editor.document val document = editor.document
@@ -80,8 +87,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
val element = file.findElementAt(offset) val element = file.findElementAt(offset)
if (!inMultilineString(element, offset)) { if (!inMultilineString(element, offset)) {
return Result.Continue return Result.Continue
} } else {
else {
wasInMultilineString = true wasInMultilineString = true
} }
@@ -171,8 +177,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
// Move closing bracket under same indent // Move closing bracket under same indent
forceIndent(caretOffset() + 1, indentSize, newMarginChar, document, settings) forceIndent(caretOffset() + 1, indentSize, newMarginChar, document, settings)
} }
} } else {
else {
val isPrevLineFirst = document.getLineNumber(literalOffset) == prevLineNumber val isPrevLineFirst = document.getLineNumber(literalOffset) == prevLineNumber
val indentInPreviousLine = when { val indentInPreviousLine = when {
@@ -190,12 +195,12 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
val marginCharToInsert = if (marginChar != null && val marginCharToInsert = if (marginChar != null &&
!prefixStripped.startsWith(marginChar) && !prefixStripped.startsWith(marginChar) &&
!nonBlankNotFirstLines.isEmpty() && !nonBlankNotFirstLines.isEmpty() &&
nonBlankNotFirstLines.none { it.trimStart().startsWith(marginChar) }) { nonBlankNotFirstLines.none { it.trimStart().startsWith(marginChar) }
) {
// We have margin char but decide not to insert it // We have margin char but decide not to insert it
null null
} } else {
else {
marginChar marginChar
} }
@@ -245,7 +250,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
class MultilineSettings(project: Project) { class MultilineSettings(project: Project) {
private val kotlinIndentOptions = private val kotlinIndentOptions =
CodeStyleSettingsManager.getInstance(project).currentSettings.getIndentOptions(KotlinFileType.INSTANCE) CodeStyleSettingsManager.getInstance(project).currentSettings.getIndentOptions(KotlinFileType.INSTANCE)
private val useTabs = kotlinIndentOptions.USE_TAB_CHARACTER private val useTabs = kotlinIndentOptions.USE_TAB_CHARACTER
private val tabSize = kotlinIndentOptions.TAB_SIZE private val tabSize = kotlinIndentOptions.TAB_SIZE
@@ -285,7 +290,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
} }
fun inMultilineString(element: PsiElement?, offset: Int) = fun inMultilineString(element: PsiElement?, offset: Int) =
!(findString(element, offset)?.isSingleQuoted() ?: true) !(findString(element, offset)?.isSingleQuoted() ?: true)
fun getMarginCharFromLiteral(str: KtStringTemplateExpression, marginChar: Char = DEFAULT_TRIM_MARGIN_CHAR): Char? { fun getMarginCharFromLiteral(str: KtStringTemplateExpression, marginChar: Char = DEFAULT_TRIM_MARGIN_CHAR): Char? {
val lines = str.text.lines() val lines = str.text.lines()
@@ -304,18 +309,17 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
private fun getLiteralCalls(str: KtStringTemplateExpression): Sequence<KtCallExpression> { private fun getLiteralCalls(str: KtStringTemplateExpression): Sequence<KtCallExpression> {
var previous: PsiElement = str var previous: PsiElement = str
return str.parents return str.parents
.takeWhile { parent -> .takeWhile { parent ->
if (parent is KtQualifiedExpression && parent.receiverExpression == previous) { if (parent is KtQualifiedExpression && parent.receiverExpression == previous) {
previous = parent previous = parent
true true
} } else {
else { false
false
}
}
.mapNotNull { qualified ->
(qualified as KtQualifiedExpression).selectorExpression as? KtCallExpression
} }
}
.mapNotNull { qualified ->
(qualified as KtQualifiedExpression).selectorExpression as? KtCallExpression
}
} }
fun getMarginCharFromTrimMarginCallsInChain(str: KtStringTemplateExpression): Char? { fun getMarginCharFromTrimMarginCallsInChain(str: KtStringTemplateExpression): Char? {
@@ -335,7 +339,7 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
} }
fun getLineByNumber(number: Int, document: Document): String = fun getLineByNumber(number: Int, document: Document): String =
document.getText(TextRange(document.getLineStartOffset(number), document.getLineEndOffset(number))) document.getText(TextRange(document.getLineStartOffset(number), document.getLineEndOffset(number)))
fun insertNewLine(nlOffset: Int, indent: Int, document: Document, settings: MultilineSettings) { fun insertNewLine(nlOffset: Int, indent: Int, document: Document, settings: MultilineSettings) {
document.insertString(nlOffset, "\n") document.insertString(nlOffset, "\n")
@@ -347,9 +351,11 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
val lineStart = document.getLineStartOffset(lineNumber) val lineStart = document.getLineStartOffset(lineNumber)
val line = getLineByNumber(lineNumber, document) val line = getLineByNumber(lineNumber, document)
val wsPrefix = line.takeWhile { c -> c == ' ' || c == '\t' } val wsPrefix = line.takeWhile { c -> c == ' ' || c == '\t' }
document.replaceString(lineStart, document.replaceString(
lineStart + wsPrefix.length, lineStart,
settings.getSmartSpaces(indent) + (marginChar?.toString() ?: "")) lineStart + wsPrefix.length,
settings.getSmartSpaces(indent) + (marginChar?.toString() ?: "")
)
} }
fun String.prefixLength(f: (Char) -> Boolean) = takeWhile(f).count() fun String.prefixLength(f: (Char) -> Boolean) = takeWhile(f).count()
@@ -360,20 +366,20 @@ class KotlinMultilineStringEnterHandler : EnterHandlerDelegateAdapter() {
if (marginChar == null) { if (marginChar == null) {
document.insertString(literal.textRange.endOffset, ".$TRIM_INDENT_CALL()") document.insertString(literal.textRange.endOffset, ".$TRIM_INDENT_CALL()")
} } else {
else {
document.insertString( document.insertString(
literal.textRange.endOffset, literal.textRange.endOffset,
if (marginChar == DEFAULT_TRIM_MARGIN_CHAR) { if (marginChar == DEFAULT_TRIM_MARGIN_CHAR) {
".$TRIM_MARGIN_CALL()" ".$TRIM_MARGIN_CALL()"
} } else {
else { ".$TRIM_MARGIN_CALL(\"$marginChar\")"
".$TRIM_MARGIN_CALL(\"$marginChar\")" }
}) )
} }
} }
private data class HostPosition(val file: PsiFile, val editor: Editor, val offset: Int) private data class HostPosition(val file: PsiFile, val editor: Editor, val offset: Int)
private fun getHostPosition(dataContext: DataContext): HostPosition? { private fun getHostPosition(dataContext: DataContext): HostPosition? {
val editor = dataContext.hostEditor as? EditorEx ?: return null val editor = dataContext.hostEditor as? EditorEx ?: return null
val project = dataContext.project val project = dataContext.project
@@ -29,8 +29,7 @@ class KotlinQuoteHandler : QuoteHandler {
val start = iterator.start val start = iterator.start
val end = iterator.end val end = iterator.end
return end - start >= 1 && offset == end - 1 return end - start >= 1 && offset == end - 1
} } else if (tokenType == KtTokens.CLOSING_QUOTE) {
else if (tokenType == KtTokens.CLOSING_QUOTE) {
return true return true
} }
return false return false
@@ -53,10 +52,10 @@ class KotlinQuoteHandler : QuoteHandler {
override fun isInsideLiteral(iterator: HighlighterIterator): Boolean { override fun isInsideLiteral(iterator: HighlighterIterator): Boolean {
val tokenType = iterator.tokenType val tokenType = iterator.tokenType
return tokenType == KtTokens.REGULAR_STRING_PART || return tokenType == KtTokens.REGULAR_STRING_PART ||
tokenType == KtTokens.OPEN_QUOTE || tokenType == KtTokens.OPEN_QUOTE ||
tokenType == KtTokens.CLOSING_QUOTE || tokenType == KtTokens.CLOSING_QUOTE ||
tokenType == KtTokens.SHORT_TEMPLATE_ENTRY_START || tokenType == KtTokens.SHORT_TEMPLATE_ENTRY_START ||
tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END || tokenType == KtTokens.LONG_TEMPLATE_ENTRY_END ||
tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START tokenType == KtTokens.LONG_TEMPLATE_ENTRY_START
} }
} }
@@ -100,7 +100,8 @@ class KotlinSmartEnterHandler : SmartEnterProcessorWithFixers() {
caretOffset = CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1 caretOffset = CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1
if (CharArrayUtil.regionMatches(chars, caretOffset - "{}".length, "{}") || if (CharArrayUtil.regionMatches(chars, caretOffset - "{}".length, "{}") ||
CharArrayUtil.regionMatches(chars, caretOffset - "{\n}".length, "{\n}")) { CharArrayUtil.regionMatches(chars, caretOffset - "{\n}".length, "{\n}")
) {
commit(editor) commit(editor)
val settings = CodeStyleSettingsManager.getSettings(file.project) val settings = CodeStyleSettingsManager.getSettings(file.project)
val old = settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE val old = settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE
@@ -150,7 +150,9 @@ public class KotlinTypedHandler extends TypedHandlerDelegate {
if (KtTokens.COMMENTS.contains(tokenType) if (KtTokens.COMMENTS.contains(tokenType)
|| tokenType == KtTokens.REGULAR_STRING_PART || tokenType == KtTokens.REGULAR_STRING_PART
|| tokenType == KtTokens.OPEN_QUOTE || tokenType == KtTokens.OPEN_QUOTE
|| tokenType == KtTokens.CHARACTER_LITERAL) return; || tokenType == KtTokens.CHARACTER_LITERAL) {
return;
}
AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null); AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
} }
@@ -187,7 +189,9 @@ public class KotlinTypedHandler extends TypedHandlerDelegate {
if (!endsWith(chars, offset, "this@") if (!endsWith(chars, offset, "this@")
&& !endsWith(chars, offset, "return@") && !endsWith(chars, offset, "return@")
&& !endsWith(chars, offset, "break@") && !endsWith(chars, offset, "break@")
&& !endsWith(chars, offset, "continue@")) return false; && !endsWith(chars, offset, "continue@")) {
return false;
}
PsiElement lastElement = file.findElementAt(offset - 1); PsiElement lastElement = file.findElementAt(offset - 1);
if (lastElement == null) return false; if (lastElement == null) return false;
@@ -233,7 +237,7 @@ public class KotlinTypedHandler extends TypedHandlerDelegate {
int offset = editor.getCaretModel().getOffset(); int offset = editor.getCaretModel().getOffset();
PsiElement previousElement = file.findElementAt(offset - 1); PsiElement previousElement = file.findElementAt(offset - 1);
if (previousElement instanceof LeafPsiElement if (previousElement instanceof LeafPsiElement
&& ((LeafPsiElement) previousElement).getElementType() == KtTokens.LONG_TEMPLATE_ENTRY_START) { && ((LeafPsiElement) previousElement).getElementType() == KtTokens.LONG_TEMPLATE_ENTRY_START) {
editor.getDocument().insertString(offset, "}"); editor.getDocument().insertString(offset, "}");
return Result.STOP; return Result.STOP;
} }
@@ -253,7 +257,8 @@ public class KotlinTypedHandler extends TypedHandlerDelegate {
if (autoIndentCase(editor, project, file, KtOperationReferenceExpression.class)) { if (autoIndentCase(editor, project, file, KtOperationReferenceExpression.class)) {
return Result.STOP; return Result.STOP;
} }
} else if (c == '&') { }
else if (c == '&') {
if (autoIndentCase(editor, project, file, KtOperationReferenceExpression.class)) { if (autoIndentCase(editor, project, file, KtOperationReferenceExpression.class)) {
return Result.STOP; return Result.STOP;
} }
@@ -264,6 +269,7 @@ public class KotlinTypedHandler extends TypedHandlerDelegate {
/** /**
* Copied from * Copied from
*
* @see com.intellij.codeInsight.editorActions.TypedHandler#indentBrace(Project, Editor, char) * @see com.intellij.codeInsight.editorActions.TypedHandler#indentBrace(Project, Editor, char)
*/ */
private static void indentBrace(@NotNull final Project project, @NotNull final Editor editor, char braceChar) { private static void indentBrace(@NotNull final Project project, @NotNull final Editor editor, char braceChar) {
@@ -37,8 +37,7 @@ class KotlinCatchParameterFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmar
val parameter = parameterList?.parameters?.firstOrNull()?.text ?: "" val parameter = parameterList?.parameters?.firstOrNull()?.text ?: ""
editor.document.replaceString(catchEnd, endOffset, "($parameter)") editor.document.replaceString(catchEnd, endOffset, "($parameter)")
processor.registerUnresolvedError(endOffset - 1) processor.registerUnresolvedError(endOffset - 1)
} } else if (parameterList.parameters.firstOrNull()?.text.isNullOrBlank()) {
else if (parameterList.parameters.firstOrNull()?.text.isNullOrBlank()) {
processor.registerUnresolvedError(parameterList.startOffset + 1) processor.registerUnresolvedError(parameterList.startOffset + 1)
} }
} }
@@ -17,11 +17,11 @@
package org.jetbrains.kotlin.idea.editor.fixers package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.lang.SmartEnterProcessorWithFixers import com.intellij.lang.SmartEnterProcessorWithFixers
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtDoWhileExpression import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import org.jetbrains.kotlin.psi.KtBlockExpression import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.psi.KtDoWhileExpression
class KotlinDoWhileFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() { class KotlinDoWhileFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) { override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, psiElement: PsiElement) {
@@ -35,13 +35,11 @@ class KotlinDoWhileFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterH
if (body == null) { if (body == null) {
if (whileKeyword == null) { if (whileKeyword == null) {
doc.replaceString(start, start + "do".length, "do {} while()") doc.replaceString(start, start + "do".length, "do {} while()")
} } else {
else {
doc.insertString(start + "do".length, "{}") doc.insertString(start + "do".length, "{}")
} }
return return
} } else if (whileKeyword != null && body !is KtBlockExpression && body.startLine(doc) > psiElement.startLine(doc)) {
else if (whileKeyword != null && body !is KtBlockExpression && body.startLine(doc) > psiElement.startLine(doc)) {
doc.insertString(whileKeyword.range.start, "}") doc.insertString(whileKeyword.range.start, "}")
doc.insertString(start + "do".length, "{") doc.insertString(start + "do".length, "{")
@@ -19,11 +19,12 @@ package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtForExpression import org.jetbrains.kotlin.psi.KtForExpression
class KotlinForConditionFixer: MissingConditionFixer<KtForExpression>() { class KotlinForConditionFixer : MissingConditionFixer<KtForExpression>() {
override val keyword = "for" override val keyword = "for"
override fun getElement(element: PsiElement?) = element as? KtForExpression override fun getElement(element: PsiElement?) = element as? KtForExpression
override fun getCondition(element: KtForExpression) = override fun getCondition(element: KtForExpression) =
element.loopRange ?: element.loopParameter ?: element.destructuringDeclaration element.loopRange ?: element.loopParameter ?: element.destructuringDeclaration
override fun getLeftParenthesis(element: KtForExpression) = element.leftParenthesis override fun getLeftParenthesis(element: KtForExpression) = element.leftParenthesis
override fun getRightParenthesis(element: KtForExpression) = element.rightParenthesis override fun getRightParenthesis(element: KtForExpression) = element.rightParenthesis
override fun getBody(element: KtForExpression) = element.body override fun getBody(element: KtForExpression) = element.body
@@ -35,8 +35,7 @@ class KotlinFunctionParametersFixer : SmartEnterProcessorWithFixers.Fixer<Kotlin
val offset = Math.max(identifier.range.end, psiElement.typeParameterList?.range?.end ?: psiElement.range.start) val offset = Math.max(identifier.range.end, psiElement.typeParameterList?.range?.end ?: psiElement.range.start)
editor.document.insertString(offset, "()") editor.document.insertString(offset, "()")
processor.registerUnresolvedError(offset + 1) processor.registerUnresolvedError(offset + 1)
} } else {
else {
val rParen = parameterList.lastChild ?: return val rParen = parameterList.lastChild ?: return
if (")" != rParen.text) { if (")" != rParen.text) {
@@ -53,8 +53,7 @@ class KotlinMissingIfBranchFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSma
if (thenBranch == null || probablyNextStatementParsedAsThen) { if (thenBranch == null || probablyNextStatementParsedAsThen) {
document.insertString(rParen.range.end, "{}") document.insertString(rParen.range.end, "{}")
} } else {
else {
document.insertString(rParen.range.end, "{") document.insertString(rParen.range.end, "{")
document.insertString(thenBranch.range.end + 1, "}") document.insertString(thenBranch.range.end + 1, "}")
} }
@@ -17,9 +17,9 @@
package org.jetbrains.kotlin.idea.editor.fixers package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.lang.SmartEnterProcessorWithFixers import com.intellij.lang.SmartEnterProcessorWithFixers
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.psi.KtWhenExpression
class KotlinMissingWhenBodyFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() { class KotlinMissingWhenBodyFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
@@ -46,17 +46,15 @@ class KotlinPropertySetterParametersFixer : SmartEnterProcessorWithFixers.Fixer<
if (parameter?.text.isNullOrBlank()) { if (parameter?.text.isNullOrBlank()) {
if (psiElement.rightParenthesis == null) { if (psiElement.rightParenthesis == null) {
doc.insertString(parameterOffset, "value)") doc.insertString(parameterOffset, "value)")
} } else {
else {
doc.insertString(parameterOffset, "value") doc.insertString(parameterOffset, "value")
} }
} } else if (psiElement.rightParenthesis == null) {
else if (psiElement.rightParenthesis == null) {
doc.insertString(parameterOffset + parameter!!.text.length, ")") doc.insertString(parameterOffset + parameter!!.text.length, ")")
} }
} }
private val KtPropertyAccessor.leftParenthesis : ASTNode? private val KtPropertyAccessor.leftParenthesis: ASTNode?
get() = node.findChildByType(KtTokens.LPAR) get() = node.findChildByType(KtTokens.LPAR)
} }
@@ -16,10 +16,10 @@
package org.jetbrains.kotlin.idea.editor.fixers package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.psi.PsiElement
import com.intellij.lang.SmartEnterProcessorWithFixers import com.intellij.lang.SmartEnterProcessorWithFixers
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
import org.jetbrains.kotlin.psi.KtWhenExpression import org.jetbrains.kotlin.psi.KtWhenExpression
class KotlinWhenSubjectCaretFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() { class KotlinWhenSubjectCaretFixer : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtWhileExpression import org.jetbrains.kotlin.psi.KtWhileExpression
class KotlinWhileConditionFixer: MissingConditionFixer<KtWhileExpression>() { class KotlinWhileConditionFixer : MissingConditionFixer<KtWhileExpression>() {
override val keyword = "while" override val keyword = "while"
override fun getElement(element: PsiElement?) = element as? KtWhileExpression override fun getElement(element: PsiElement?) = element as? KtWhileExpression
override fun getCondition(element: KtWhileExpression) = element.condition override fun getCondition(element: KtWhileExpression) = element.condition
@@ -21,7 +21,7 @@ import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler import org.jetbrains.kotlin.idea.editor.KotlinSmartEnterHandler
abstract class MissingConditionFixer<T: PsiElement> : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() { abstract class MissingConditionFixer<T : PsiElement> : SmartEnterProcessorWithFixers.Fixer<KotlinSmartEnterHandler>() {
override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) { override fun apply(editor: Editor, processor: KotlinSmartEnterHandler, element: PsiElement) {
val workElement = getElement(element) ?: return val workElement = getElement(element) ?: return
@@ -42,12 +42,10 @@ abstract class MissingConditionFixer<T: PsiElement> : SmartEnterProcessorWithFix
doc.replaceString(workElement.range.start, stopOffset, "$keyword ()") doc.replaceString(workElement.range.start, stopOffset, "$keyword ()")
processor.registerUnresolvedError(workElement.range.start + "$keyword (".length) processor.registerUnresolvedError(workElement.range.start + "$keyword (".length)
} } else {
else {
processor.registerUnresolvedError(lParen.range.end) processor.registerUnresolvedError(lParen.range.end)
} }
} } else {
else {
if (rParen == null) { if (rParen == null) {
doc.insertString(condition.range.end, ")") doc.insertString(condition.range.end, ")")
} }
@@ -16,9 +16,9 @@
package org.jetbrains.kotlin.idea.editor.fixers package org.jetbrains.kotlin.idea.editor.fixers
import com.intellij.psi.PsiElement
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Document
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
val PsiElement.range: TextRange get() = textRange!! val PsiElement.range: TextRange get() = textRange!!
val TextRange.start: Int get() = startOffset val TextRange.start: Int get() = startOffset
@@ -26,8 +26,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
class KotlinCallExpressionWithLambdaSelectioner : ExtendWordSelectionHandlerBase() { class KotlinCallExpressionWithLambdaSelectioner : ExtendWordSelectionHandlerBase() {
override fun canSelect(e: PsiElement): Boolean override fun canSelect(e: PsiElement): Boolean = e is KtCallExpression && e.hasLambda()
= e is KtCallExpression && e.hasLambda()
override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? { override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? {
if (e !is KtCallExpression) return null if (e !is KtCallExpression) return null
@@ -36,7 +35,6 @@ class KotlinCallExpressionWithLambdaSelectioner : ExtendWordSelectionHandlerBase
return listOf(TextRange(e.startOffset, endOffset)) return listOf(TextRange(e.startOffset, endOffset))
} }
private fun KtCallExpression.hasLambda(): Boolean private fun KtCallExpression.hasLambda(): Boolean = lambdaArguments.isNotEmpty()
= lambdaArguments.isNotEmpty()
} }
@@ -30,8 +30,7 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
import java.util.* import java.util.*
class KotlinDeclarationSelectioner : ExtendWordSelectionHandlerBase() { class KotlinDeclarationSelectioner : ExtendWordSelectionHandlerBase() {
override fun canSelect(e: PsiElement) override fun canSelect(e: PsiElement) = e is KtDeclaration
= e is KtDeclaration
override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? { override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? {
if (e is KtDestructuringDeclaration) { if (e is KtDestructuringDeclaration) {
@@ -42,27 +41,29 @@ class KotlinDeclarationSelectioner : ExtendWordSelectionHandlerBase() {
val firstChild = e.firstChild val firstChild = e.firstChild
val firstComment = firstChild val firstComment = firstChild
.siblings(forward = true, withItself = true) .siblings(forward = true, withItself = true)
.firstOrNull { it is PsiComment } .firstOrNull { it is PsiComment }
val firstNonComment = firstChild val firstNonComment = firstChild
.siblings(forward = true, withItself = true) .siblings(forward = true, withItself = true)
.first { it !is PsiComment && it !is PsiWhiteSpace } .first { it !is PsiComment && it !is PsiWhiteSpace }
val lastChild = e.lastChild val lastChild = e.lastChild
val lastComment = lastChild val lastComment = lastChild
.siblings(forward = false, withItself = true) .siblings(forward = false, withItself = true)
.firstOrNull { it is PsiComment } .firstOrNull { it is PsiComment }
val lastNonComment = lastChild val lastNonComment = lastChild
.siblings(forward = false, withItself = true) .siblings(forward = false, withItself = true)
.first { it !is PsiComment && it !is PsiWhiteSpace } .first { it !is PsiComment && it !is PsiWhiteSpace }
if (firstComment != null || lastComment != null) { if (firstComment != null || lastComment != null) {
val startOffset = minOf( val startOffset = minOf(
firstComment?.startOffset ?: Int.MAX_VALUE, firstComment?.startOffset ?: Int.MAX_VALUE,
lastNonComment.startOffset) lastNonComment.startOffset
)
val endOffset = maxOf( val endOffset = maxOf(
lastComment?.endOffset ?: Int.MIN_VALUE, lastComment?.endOffset ?: Int.MIN_VALUE,
lastNonComment.endOffset) lastNonComment.endOffset
)
result.addRange(editorText, TextRange(startOffset, endOffset)) result.addRange(editorText, TextRange(startOffset, endOffset))
} }
@@ -16,16 +16,14 @@
package org.jetbrains.kotlin.idea.editor.wordSelection package org.jetbrains.kotlin.idea.editor.wordSelection
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import org.jetbrains.kotlin.kdoc.psi.api.KDoc import org.jetbrains.kotlin.kdoc.psi.api.KDoc
class KotlinDocCommentSelectioner : ExtendWordSelectionHandlerBase() { class KotlinDocCommentSelectioner : ExtendWordSelectionHandlerBase() {
override fun canSelect(e: PsiElement) override fun canSelect(e: PsiElement) = e is KDoc
= e is KDoc
override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? { override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? {
return ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, e.textRange) return ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, e.textRange)
@@ -16,21 +16,21 @@
package org.jetbrains.kotlin.idea.editor.wordSelection package org.jetbrains.kotlin.idea.editor.wordSelection
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtParameterList import org.jetbrains.kotlin.psi.KtParameterList
import org.jetbrains.kotlin.psi.KtTypeArgumentList import org.jetbrains.kotlin.psi.KtTypeArgumentList
import org.jetbrains.kotlin.psi.KtTypeParameterList import org.jetbrains.kotlin.psi.KtTypeParameterList
import org.jetbrains.kotlin.psi.KtValueArgumentList import org.jetbrains.kotlin.psi.KtValueArgumentList
import org.jetbrains.kotlin.lexer.KtTokens
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
class KotlinListSelectioner : ExtendWordSelectionHandlerBase() { class KotlinListSelectioner : ExtendWordSelectionHandlerBase() {
companion object { companion object {
fun canSelect(e: PsiElement) fun canSelect(e: PsiElement) =
= e is KtParameterList || e is KtValueArgumentList || e is KtTypeParameterList || e is KtTypeArgumentList e is KtParameterList || e is KtValueArgumentList || e is KtTypeParameterList || e is KtTypeArgumentList
} }
override fun canSelect(e: PsiElement) = KotlinListSelectioner.canSelect(e) override fun canSelect(e: PsiElement) = KotlinListSelectioner.canSelect(e)
@@ -41,8 +41,10 @@ class KotlinListSelectioner : ExtendWordSelectionHandlerBase() {
val endNode = node.findChildByType(TokenSet.create(KtTokens.RPAR, KtTokens.GT)) ?: return null val endNode = node.findChildByType(TokenSet.create(KtTokens.RPAR, KtTokens.GT)) ?: return null
val innerRange = TextRange(startNode.startOffset + 1, endNode.startOffset) val innerRange = TextRange(startNode.startOffset + 1, endNode.startOffset)
if (e is KtTypeArgumentList || e is KtTypeParameterList) { if (e is KtTypeArgumentList || e is KtTypeParameterList) {
return listOf(innerRange, return listOf(
TextRange(startNode.startOffset, endNode.startOffset + endNode.textLength)) innerRange,
TextRange(startNode.startOffset, endNode.startOffset + endNode.textLength)
)
} }
return listOf(innerRange) return listOf(innerRange)
} }
@@ -16,17 +16,16 @@
package org.jetbrains.kotlin.idea.editor.wordSelection package org.jetbrains.kotlin.idea.editor.wordSelection
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import org.jetbrains.kotlin.psi.psiUtil.siblings
import com.intellij.psi.PsiComment
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.siblings
/** /**
* Originally from IDEA platform: StatementGroupSelectioner * Originally from IDEA platform: StatementGroupSelectioner
@@ -42,23 +41,31 @@ class KotlinStatementGroupSelectioner : ExtendWordSelectionHandlerBase() {
val parent = e.parent val parent = e.parent
val startElement = e.siblings(forward = false, withItself = false) val startElement = e.siblings(forward = false, withItself = false)
.firstOrNull { // find preceding '{' or blank line .firstOrNull {
it is LeafPsiElement && it.elementType == KtTokens.LBRACE || // find preceding '{' or blank line
it is PsiWhiteSpace && it.getText()!!.count { it == '\n' } > 1 it is LeafPsiElement && it.elementType == KtTokens.LBRACE ||
} it is PsiWhiteSpace && it.getText()!!.count { it == '\n' } > 1
?.siblings(forward = true, withItself = false) }
?.dropWhile { it is PsiWhiteSpace } // and take first non-whitespace element after it ?.siblings(forward = true, withItself = false)
?.firstOrNull() ?: parent.firstChild!! ?.dropWhile { it is PsiWhiteSpace } // and take first non-whitespace element after it
?.firstOrNull() ?: parent.firstChild!!
val endElement = e.siblings(forward = true, withItself = false) val endElement = e.siblings(forward = true, withItself = false)
.firstOrNull { // find next '}' or blank line .firstOrNull {
it is LeafPsiElement && it.elementType == KtTokens.RBRACE || // find next '}' or blank line
it is PsiWhiteSpace && it.getText()!!.count { it == '\n' } > 1 it is LeafPsiElement && it.elementType == KtTokens.RBRACE ||
} it is PsiWhiteSpace && it.getText()!!.count { it == '\n' } > 1
?.siblings(forward = false, withItself = false) }
?.dropWhile { it is PsiWhiteSpace } // and take first non-whitespace element before it ?.siblings(forward = false, withItself = false)
?.firstOrNull() ?: parent.lastChild!! ?.dropWhile { it is PsiWhiteSpace } // and take first non-whitespace element before it
?.firstOrNull() ?: parent.lastChild!!
return ExtendWordSelectionHandlerBase.expandToWholeLine(editorText, TextRange(startElement.textRange!!.startOffset, endElement.textRange!!.endOffset)) return ExtendWordSelectionHandlerBase.expandToWholeLine(
editorText,
TextRange(
startElement.textRange!!.startOffset,
endElement.textRange!!.endOffset
)
)
} }
} }
@@ -17,9 +17,9 @@
package org.jetbrains.kotlin.idea.editor.wordSelection package org.jetbrains.kotlin.idea.editor.wordSelection
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase
import com.intellij.psi.PsiElement
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.psi.KtStringTemplateExpression import org.jetbrains.kotlin.psi.KtStringTemplateExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
@@ -32,8 +32,8 @@ class KotlinTypeSelectioner : ExtendWordSelectionHandlerBase() {
override fun canSelect(e: PsiElement): Boolean { override fun canSelect(e: PsiElement): Boolean {
return e is KtTypeReference return e is KtTypeReference
&& e.getStrictParentOfType<KtObjectDeclaration>() == null && e.getStrictParentOfType<KtObjectDeclaration>() == null
&& e.getStrictParentOfType<KtParameter>() == null && e.getStrictParentOfType<KtParameter>() == null
} }
override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? { override fun select(e: PsiElement, editorText: CharSequence, cursorOffset: Int, editor: Editor): List<TextRange>? {
@@ -18,13 +18,13 @@ package org.jetbrains.kotlin.idea.editor.wordSelection
import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Condition
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.KtNodeTypes.* import org.jetbrains.kotlin.KtNodeTypes.BLOCK
import org.jetbrains.kotlin.psi.KtContainerNode
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes import org.jetbrains.kotlin.kdoc.parser.KDocElementTypes
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtContainerNode
class KotlinWordSelectionFilter : Condition<PsiElement>{ class KotlinWordSelectionFilter : Condition<PsiElement> {
override fun value(e: PsiElement): Boolean { override fun value(e: PsiElement): Boolean {
if (e.language != KotlinLanguage.INSTANCE) return true if (e.language != KotlinLanguage.INSTANCE) return true