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 com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.SmartPointerManager
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
|
||||
|
||||
public object ShortenReferences {
|
||||
@@ -30,13 +31,19 @@ public object ShortenReferences {
|
||||
}
|
||||
|
||||
public fun process(file: JetFile, startOffset: Int, endOffset: Int) {
|
||||
val smartPointerManager = SmartPointerManager.getInstance(file.getProject())
|
||||
val pointer = smartPointerManager.createSmartPsiFileRangePointer(file, TextRange(startOffset, endOffset))
|
||||
val documentManager = PsiDocumentManager.getInstance(file.getProject())
|
||||
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 {
|
||||
process(listOf(file), { element ->
|
||||
val segment = pointer.getRange()
|
||||
if (segment != null) {
|
||||
val range = TextRange(segment.getStartOffset(), segment.getEndOffset())
|
||||
if (rangeMarker.isValid()) {
|
||||
val range = TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset())
|
||||
val elementRange = element.getTextRange()!!
|
||||
when {
|
||||
range.contains(elementRange) -> FilterResult.PROCESS
|
||||
@@ -50,7 +57,7 @@ public object ShortenReferences {
|
||||
})
|
||||
}
|
||||
finally {
|
||||
smartPointerManager.removePointer(pointer)
|
||||
rangeMarker.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,14 +93,6 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
|
||||
val lookupString = qualifierPresentation + "." + lookupElement.getLookupString()
|
||||
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) {
|
||||
override fun getLookupString() = lookupString
|
||||
|
||||
@@ -123,19 +115,16 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
val editor = context.getEditor()
|
||||
val startOffset = context.getStartOffset()
|
||||
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) {
|
||||
text += "()"
|
||||
//TODO: auto-popup parameter info and other functionality from JetFunctionInsertHandler
|
||||
getDelegate().handleInsert(context)
|
||||
}
|
||||
|
||||
editor.getDocument().replaceString(startOffset, context.getTailOffset(), text)
|
||||
val endOffset = startOffset + text.length
|
||||
editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset)
|
||||
|
||||
shortenReferences(context, startOffset, startOffset + qualifierText.length)
|
||||
shortenReferences(context, context.getStartOffset(), context.getTailOffset())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.jet.completion.AbstractJvmBasicCompletionTest;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
|
||||
+18
-2
@@ -16,11 +16,17 @@
|
||||
|
||||
package org.jetbrains.jet.completion.handlers;
|
||||
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.io.File;
|
||||
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 */
|
||||
@SuppressWarnings("all")
|
||||
@@ -60,6 +66,16 @@ public class SmartCompletionHandlerTestGenerated extends AbstractSmartCompletion
|
||||
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")
|
||||
public void testClosingParenthesis1() throws Exception {
|
||||
doTest("idea/testData/completion/handlers/smart/ClosingParenthesis1.kt");
|
||||
|
||||
@@ -31,7 +31,7 @@ abstract class AbstractShortenRefsTest : LightCodeInsightFixtureTestCase() {
|
||||
override fun getProjectDescriptor() = JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||
|
||||
protected fun doTest(testPath: String) {
|
||||
val fixture = myFixture!!
|
||||
val fixture = myFixture
|
||||
val dependencyPath = testPath.replace(".kt", ".dependency.kt")
|
||||
if (File(dependencyPath).exists()) {
|
||||
fixture.configureByFile(dependencyPath)
|
||||
@@ -44,13 +44,12 @@ abstract class AbstractShortenRefsTest : LightCodeInsightFixtureTestCase() {
|
||||
fixture.configureByFile(testPath)
|
||||
|
||||
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")
|
||||
val element = PsiTreeUtil.findElementOfClassAtRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), javaClass<JetElement>())!!
|
||||
|
||||
CommandProcessor.getInstance()!!.executeCommand(getProject(), {
|
||||
CommandProcessor.getInstance().executeCommand(getProject(), {
|
||||
ApplicationManager.getApplication()!!.runWriteAction {
|
||||
ShortenReferences.process(element)
|
||||
ShortenReferences.process(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd())
|
||||
}
|
||||
}, null, null)
|
||||
selectionModel.removeSelection()
|
||||
|
||||
Reference in New Issue
Block a user