Smart completion: static members insertion reworked to support single lambda parameter, more correct reference shortening in range
This commit is contained in:
@@ -18,6 +18,7 @@ import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyPackageFragmentF
|
|||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor
|
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.SmartPointerManager
|
import com.intellij.psi.SmartPointerManager
|
||||||
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||||
|
|
||||||
public object ShortenReferences {
|
public object ShortenReferences {
|
||||||
@@ -30,13 +31,19 @@ public object ShortenReferences {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun process(file: JetFile, startOffset: Int, endOffset: Int) {
|
public fun process(file: JetFile, startOffset: Int, endOffset: Int) {
|
||||||
val smartPointerManager = SmartPointerManager.getInstance(file.getProject())
|
val documentManager = PsiDocumentManager.getInstance(file.getProject())
|
||||||
val pointer = smartPointerManager.createSmartPsiFileRangePointer(file, TextRange(startOffset, endOffset))
|
val document = documentManager.getDocument(file)!!
|
||||||
|
if (!documentManager.isCommitted(document)) {
|
||||||
|
throw IllegalStateException("Document should be committed to shorten references in range")
|
||||||
|
}
|
||||||
|
|
||||||
|
val rangeMarker = document.createRangeMarker(startOffset, endOffset)
|
||||||
|
rangeMarker.setGreedyToLeft(true)
|
||||||
|
rangeMarker.setGreedyToRight(true)
|
||||||
try {
|
try {
|
||||||
process(listOf(file), { element ->
|
process(listOf(file), { element ->
|
||||||
val segment = pointer.getRange()
|
if (rangeMarker.isValid()) {
|
||||||
if (segment != null) {
|
val range = TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset())
|
||||||
val range = TextRange(segment.getStartOffset(), segment.getEndOffset())
|
|
||||||
val elementRange = element.getTextRange()!!
|
val elementRange = element.getTextRange()!!
|
||||||
when {
|
when {
|
||||||
range.contains(elementRange) -> FilterResult.PROCESS
|
range.contains(elementRange) -> FilterResult.PROCESS
|
||||||
@@ -50,7 +57,7 @@ public object ShortenReferences {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
smartPointerManager.removePointer(pointer)
|
rangeMarker.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,14 +93,6 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
|
|||||||
val lookupString = qualifierPresentation + "." + lookupElement.getLookupString()
|
val lookupString = qualifierPresentation + "." + lookupElement.getLookupString()
|
||||||
val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords
|
val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords
|
||||||
|
|
||||||
val caretPosition: CaretPosition?
|
|
||||||
if (memberDescriptor is FunctionDescriptor) {
|
|
||||||
caretPosition = if (memberDescriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
caretPosition = null
|
|
||||||
}
|
|
||||||
|
|
||||||
return object: LookupElementDecorator<LookupElement>(lookupElement) {
|
return object: LookupElementDecorator<LookupElement>(lookupElement) {
|
||||||
override fun getLookupString() = lookupString
|
override fun getLookupString() = lookupString
|
||||||
|
|
||||||
@@ -123,19 +115,16 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInsert(context: InsertionContext) {
|
override fun handleInsert(context: InsertionContext) {
|
||||||
val editor = context.getEditor()
|
|
||||||
val startOffset = context.getStartOffset()
|
|
||||||
var text = qualifierText + "." + memberDescriptor.getName().asString() //TODO: escape
|
var text = qualifierText + "." + memberDescriptor.getName().asString() //TODO: escape
|
||||||
|
|
||||||
|
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), text)
|
||||||
|
context.setTailOffset(context.getStartOffset() + text.length)
|
||||||
|
|
||||||
if (memberDescriptor is FunctionDescriptor) {
|
if (memberDescriptor is FunctionDescriptor) {
|
||||||
text += "()"
|
getDelegate().handleInsert(context)
|
||||||
//TODO: auto-popup parameter info and other functionality from JetFunctionInsertHandler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.getDocument().replaceString(startOffset, context.getTailOffset(), text)
|
shortenReferences(context, context.getStartOffset(), context.getTailOffset())
|
||||||
val endOffset = startOffset + text.length
|
|
||||||
editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset)
|
|
||||||
|
|
||||||
shortenReferences(context, startOffset, startOffset + qualifierText.length)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package sample
|
||||||
|
|
||||||
|
class K {
|
||||||
|
class object {
|
||||||
|
fun bar(p: () -> Unit): K = K()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(){
|
||||||
|
val k : K = <caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: K.bar
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package sample
|
||||||
|
|
||||||
|
class K {
|
||||||
|
class object {
|
||||||
|
fun bar(p: () -> Unit): K = K()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(){
|
||||||
|
val k : K = K.bar { <caret> }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: K.bar
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package sample
|
||||||
|
|
||||||
|
class K {
|
||||||
|
class object {
|
||||||
|
fun bar(p: (Int, String) -> Unit): K = K()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(){
|
||||||
|
val k : K = <caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: K.bar
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package sample
|
||||||
|
|
||||||
|
class K {
|
||||||
|
class object {
|
||||||
|
fun bar(p: (Int, String) -> Unit): K = K()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(){
|
||||||
|
val k : K = K.bar(<caret>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: K.bar
|
||||||
@@ -16,14 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.completion;
|
package org.jetbrains.jet.completion;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
import java.io.File;
|
import org.jetbrains.jet.completion.AbstractJvmBasicCompletionTest;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
|
|||||||
+18
-2
@@ -16,11 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.completion.handlers;
|
package org.jetbrains.jet.completion.handlers;
|
||||||
|
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import junit.framework.Assert;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.completion.handlers.AbstractSmartCompletionHandlerTest;
|
||||||
|
|
||||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
@@ -60,6 +66,16 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
|
|||||||
doTest("idea/testData/completion/handlers/smart/ClassObjectMethod2.kt");
|
doTest("idea/testData/completion/handlers/smart/ClassObjectMethod2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassObjectMethod3.kt")
|
||||||
|
public void testClassObjectMethod3() throws Exception {
|
||||||
|
doTest("idea/testData/completion/handlers/smart/ClassObjectMethod3.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ClassObjectMethod4.kt")
|
||||||
|
public void testClassObjectMethod4() throws Exception {
|
||||||
|
doTest("idea/testData/completion/handlers/smart/ClassObjectMethod4.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ClosingParenthesis1.kt")
|
@TestMetadata("ClosingParenthesis1.kt")
|
||||||
public void testClosingParenthesis1() throws Exception {
|
public void testClosingParenthesis1() throws Exception {
|
||||||
doTest("idea/testData/completion/handlers/smart/ClosingParenthesis1.kt");
|
doTest("idea/testData/completion/handlers/smart/ClosingParenthesis1.kt");
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ abstract class AbstractShortenRefsTest : LightCodeInsightFixtureTestCase() {
|
|||||||
override fun getProjectDescriptor() = JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
override fun getProjectDescriptor() = JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
protected fun doTest(testPath: String) {
|
protected fun doTest(testPath: String) {
|
||||||
val fixture = myFixture!!
|
val fixture = myFixture
|
||||||
val dependencyPath = testPath.replace(".kt", ".dependency.kt")
|
val dependencyPath = testPath.replace(".kt", ".dependency.kt")
|
||||||
if (File(dependencyPath).exists()) {
|
if (File(dependencyPath).exists()) {
|
||||||
fixture.configureByFile(dependencyPath)
|
fixture.configureByFile(dependencyPath)
|
||||||
@@ -44,13 +44,12 @@ abstract class AbstractShortenRefsTest : LightCodeInsightFixtureTestCase() {
|
|||||||
fixture.configureByFile(testPath)
|
fixture.configureByFile(testPath)
|
||||||
|
|
||||||
val file = fixture.getFile() as JetFile
|
val file = fixture.getFile() as JetFile
|
||||||
val selectionModel = fixture.getEditor()!!.getSelectionModel()
|
val selectionModel = fixture.getEditor().getSelectionModel()
|
||||||
if (!selectionModel.hasSelection()) error("No selection in input file")
|
if (!selectionModel.hasSelection()) error("No selection in input file")
|
||||||
val element = PsiTreeUtil.findElementOfClassAtRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), javaClass<JetElement>())!!
|
|
||||||
|
|
||||||
CommandProcessor.getInstance()!!.executeCommand(getProject(), {
|
CommandProcessor.getInstance().executeCommand(getProject(), {
|
||||||
ApplicationManager.getApplication()!!.runWriteAction {
|
ApplicationManager.getApplication()!!.runWriteAction {
|
||||||
ShortenReferences.process(element)
|
ShortenReferences.process(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd())
|
||||||
}
|
}
|
||||||
}, null, null)
|
}, null, null)
|
||||||
selectionModel.removeSelection()
|
selectionModel.removeSelection()
|
||||||
|
|||||||
Reference in New Issue
Block a user