FIR IDE: add completion support to classes and to type aliases
This commit is contained in:
committed by
TeamCityServer
parent
a5c33c8d42
commit
da6c5e13d5
-1
@@ -31,7 +31,6 @@ class RawFirFragmentForLazyBodiesBuilder private constructor(
|
||||
designation: List<FirDeclaration>,
|
||||
declaration: KtDeclaration,
|
||||
): FirDeclaration {
|
||||
require(declaration is KtNamedFunction || declaration is KtProperty) { "Not implemented for ${declaration::class.qualifiedName}" }
|
||||
val builder = RawFirFragmentForLazyBodiesBuilder(session, baseScopeProvider, declaration)
|
||||
builder.context.packageFqName = declaration.containingKtFile.packageFqName
|
||||
return builder.moveNext(designation.iterator())
|
||||
|
||||
+1
@@ -365,6 +365,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
}
|
||||
doTransformTypeParameters(typeAlias)
|
||||
typeAlias.transformAnnotations(transformer, data)
|
||||
transformer.onBeforeDeclarationContentResolve(typeAlias)
|
||||
typeAlias.transformExpandedTypeRef(transformer, data)
|
||||
return typeAlias
|
||||
}
|
||||
|
||||
+24
@@ -81,3 +81,27 @@ inline fun buildRegularClass(init: FirRegularClassBuilder.() -> Unit): FirRegula
|
||||
}
|
||||
return FirRegularClassBuilder().apply(init).build()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun buildRegularClassCopy(original: FirRegularClass, init: FirRegularClassBuilder.() -> Unit): FirRegularClass {
|
||||
contract {
|
||||
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val copyBuilder = FirRegularClassBuilder()
|
||||
copyBuilder.source = original.source
|
||||
copyBuilder.session = original.session
|
||||
copyBuilder.resolvePhase = original.resolvePhase
|
||||
copyBuilder.origin = original.origin
|
||||
copyBuilder.attributes = original.attributes.copy()
|
||||
copyBuilder.annotations.addAll(original.annotations)
|
||||
copyBuilder.typeParameters.addAll(original.typeParameters)
|
||||
copyBuilder.status = original.status
|
||||
copyBuilder.classKind = original.classKind
|
||||
copyBuilder.declarations.addAll(original.declarations)
|
||||
copyBuilder.scopeProvider = original.scopeProvider
|
||||
copyBuilder.name = original.name
|
||||
copyBuilder.symbol = original.symbol
|
||||
copyBuilder.companionObject = original.companionObject
|
||||
copyBuilder.superTypeRefs.addAll(original.superTypeRefs)
|
||||
return copyBuilder.apply(init).build()
|
||||
}
|
||||
|
||||
+20
@@ -68,3 +68,23 @@ inline fun buildTypeAlias(init: FirTypeAliasBuilder.() -> Unit): FirTypeAlias {
|
||||
}
|
||||
return FirTypeAliasBuilder().apply(init).build()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
inline fun buildTypeAliasCopy(original: FirTypeAlias, init: FirTypeAliasBuilder.() -> Unit): FirTypeAlias {
|
||||
contract {
|
||||
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
val copyBuilder = FirTypeAliasBuilder()
|
||||
copyBuilder.source = original.source
|
||||
copyBuilder.session = original.session
|
||||
copyBuilder.resolvePhase = original.resolvePhase
|
||||
copyBuilder.origin = original.origin
|
||||
copyBuilder.attributes = original.attributes.copy()
|
||||
copyBuilder.status = original.status
|
||||
copyBuilder.typeParameters.addAll(original.typeParameters)
|
||||
copyBuilder.name = original.name
|
||||
copyBuilder.symbol = original.symbol
|
||||
copyBuilder.expandedTypeRef = original.expandedTypeRef
|
||||
copyBuilder.annotations.addAll(original.annotations)
|
||||
return copyBuilder.apply(init).build()
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ inline fun <reified T : ConeKotlinType> FirTypeRef.coneTypeSafe(): T? {
|
||||
return (this as? FirResolvedTypeRef)?.type as? T
|
||||
}
|
||||
|
||||
inline val FirTypeRef.coneType: ConeKotlinType
|
||||
val FirTypeRef.coneType: ConeKotlinType
|
||||
get() = coneTypeSafe()
|
||||
?: error("Expected FirResolvedTypeRef with ConeKotlinType but was ${this::class.simpleName} ${render()}")
|
||||
|
||||
|
||||
+2
@@ -37,6 +37,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
|
||||
parents += typeParameterRefsOwnerBuilder
|
||||
defaultNull("companionObject")
|
||||
openBuilder()
|
||||
withCopy()
|
||||
}
|
||||
|
||||
val qualifiedAccessBuilder by builder {
|
||||
@@ -95,6 +96,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator<FirTreeBuilder>(FirTree
|
||||
|
||||
builder(typeAlias) {
|
||||
parents += typeParametersOwnerBuilder
|
||||
withCopy()
|
||||
}
|
||||
|
||||
builder(annotationCall) {
|
||||
|
||||
@@ -11,3 +11,4 @@ class A() : My<caret> {
|
||||
}
|
||||
|
||||
// EXIST: MySecondClass, MyFirstClass
|
||||
// FIR_COMPARISON
|
||||
|
||||
+2
-1
@@ -8,4 +8,5 @@ class ChromePageManager(): PageManager(object : Runnable {
|
||||
}) {
|
||||
}
|
||||
|
||||
// EXIST: Tab
|
||||
// EXIST: Tab
|
||||
// FIR_COMPARISON
|
||||
@@ -11,4 +11,5 @@ public class Test : String<caret> {
|
||||
|
||||
// EXIST: StringMy
|
||||
// EXIST: String
|
||||
// ABSENT: StringMethod
|
||||
// ABSENT: StringMethod
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,7 @@
|
||||
class X {
|
||||
init {
|
||||
val y = 1
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
// EXIST: y
|
||||
@@ -0,0 +1,9 @@
|
||||
class X {
|
||||
val x: Int = 10
|
||||
|
||||
init {
|
||||
<caret>
|
||||
}
|
||||
}
|
||||
// EXIST: x
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,5 @@
|
||||
open class Base
|
||||
class A : <caret>
|
||||
|
||||
// EXIST: Base
|
||||
// FIR_COMPARISON
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
open class Base
|
||||
class A : B<caret>
|
||||
|
||||
// EXIST: Base
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,5 @@
|
||||
open class Base<T>
|
||||
class A<U> : Base<<caret>>
|
||||
|
||||
// EXIST: U
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,8 @@
|
||||
class X {
|
||||
typealias Y = <caret>
|
||||
}
|
||||
|
||||
class Z
|
||||
|
||||
// EXIST: Z
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,5 @@
|
||||
typealias Y = <caret>
|
||||
class Z
|
||||
|
||||
// EXIST: Z
|
||||
// FIR_COMPARISON
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
val y = 10
|
||||
|
||||
class X(val x: Int = <caret>)
|
||||
|
||||
// EXIST: y
|
||||
// FIR_COMPARISON
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
class X(val y: Int, val x: Int = <caret>)
|
||||
|
||||
// EXIST: y
|
||||
// FIR_COMPARISON
|
||||
@@ -0,0 +1,6 @@
|
||||
class Y
|
||||
|
||||
class X(val x: <caret>)
|
||||
|
||||
// EXIST: Y
|
||||
// FIR_COMPARISON
|
||||
@@ -4,4 +4,5 @@ annotation class SomeAnnotation
|
||||
|
||||
class Complete(@set:Some<caret> var field: Int)
|
||||
|
||||
// ELEMENT: SomeAnnotation
|
||||
// ELEMENT: SomeAnnotation
|
||||
// FIR_COMPARISON
|
||||
@@ -4,4 +4,5 @@ annotation class SomeAnnotation
|
||||
|
||||
class Complete(@set:SomeAnnotation<caret> var field: Int)
|
||||
|
||||
// ELEMENT: SomeAnnotation
|
||||
// ELEMENT: SomeAnnotation
|
||||
// FIR_COMPARISON
|
||||
@@ -1,3 +1,4 @@
|
||||
package some
|
||||
|
||||
class Complete(@set:SomeAnn<caret> var field: Int)
|
||||
// FIR_COMPARISON
|
||||
@@ -3,3 +3,4 @@ package some
|
||||
import other.SomeAnnotation
|
||||
|
||||
class Complete(@set:SomeAnnotation<caret> var field: Int)
|
||||
// FIR_COMPARISON
|
||||
+102
@@ -1677,6 +1677,29 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InInitBlock extends AbstractJSBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInInitBlock() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("localVariable.kt")
|
||||
public void testLocalVariable() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1720,6 +1743,57 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InSuperTypes extends AbstractJSBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInSuperTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("baseClass.kt")
|
||||
public void testBaseClass() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("baseClassWithPrefix.kt")
|
||||
public void testBaseClassWithPrefix() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameter.kt")
|
||||
public void testTypeParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InTypeAlias extends AbstractJSBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInTypeAlias() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("member.kt")
|
||||
public void testMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -2231,6 +2305,34 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PrimaryConstructor extends AbstractJSBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPrimaryConstructor() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterDefaultValue.kt")
|
||||
public void testParameterDefaultValue() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("previousParameter.kt")
|
||||
public void testPreviousParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyType.kt")
|
||||
public void testPropertyType() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+102
@@ -1677,6 +1677,29 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InInitBlock extends AbstractJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInInitBlock() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("localVariable.kt")
|
||||
public void testLocalVariable() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1720,6 +1743,57 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InSuperTypes extends AbstractJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInSuperTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("baseClass.kt")
|
||||
public void testBaseClass() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("baseClassWithPrefix.kt")
|
||||
public void testBaseClassWithPrefix() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameter.kt")
|
||||
public void testTypeParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InTypeAlias extends AbstractJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInTypeAlias() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("member.kt")
|
||||
public void testMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -2231,6 +2305,34 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PrimaryConstructor extends AbstractJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPrimaryConstructor() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterDefaultValue.kt")
|
||||
public void testParameterDefaultValue() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("previousParameter.kt")
|
||||
public void testPreviousParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyType.kt")
|
||||
public void testPropertyType() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+102
@@ -1677,6 +1677,29 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inInitBlock")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InInitBlock extends AbstractHighLevelJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInInitBlock() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inInitBlock"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("localVariable.kt")
|
||||
public void testLocalVariable() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/localVariable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inInitBlock/property.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inStringLiterals")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -1720,6 +1743,57 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inSuperTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InSuperTypes extends AbstractHighLevelJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInSuperTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inSuperTypes"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("baseClass.kt")
|
||||
public void testBaseClass() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("baseClassWithPrefix.kt")
|
||||
public void testBaseClassWithPrefix() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/baseClassWithPrefix.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameter.kt")
|
||||
public void testTypeParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inSuperTypes/typeParameter.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/inTypeAlias")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class InTypeAlias extends AbstractHighLevelJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInTypeAlias() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/inTypeAlias"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("member.kt")
|
||||
public void testMember() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/member.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/inTypeAlias/topLevel.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/lambdaSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -2231,6 +2305,34 @@ public class HighLevelJvmBasicCompletionTestGenerated extends AbstractHighLevelJ
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primaryConstructor")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PrimaryConstructor extends AbstractHighLevelJvmBasicCompletionTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPrimaryConstructor() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-completion/testData/basic/common/primaryConstructor"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterDefaultValue.kt")
|
||||
public void testParameterDefaultValue() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/parameterDefaultValue.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("previousParameter.kt")
|
||||
public void testPreviousParameter() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/previousParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyType.kt")
|
||||
public void testPropertyType() throws Exception {
|
||||
runTest("idea/idea-completion/testData/basic/common/primaryConstructor/propertyType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/idea-completion/testData/basic/common/primitiveCompletion")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+56
-16
@@ -8,14 +8,11 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirFragmentForLazyBodiesBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildPropertyAccessorCopy
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunctionCopy
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.providers.firIdeProvider
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
object DeclarationCopyBuilder {
|
||||
fun createDeclarationCopy(
|
||||
@@ -24,26 +21,36 @@ object DeclarationCopyBuilder {
|
||||
state: FirModuleResolveState,
|
||||
): FirDeclaration {
|
||||
return when (fakeKtDeclaration) {
|
||||
is KtNamedFunction -> buildFunctionCopy(
|
||||
is KtNamedFunction -> createFunctionCopy(
|
||||
fakeKtDeclaration,
|
||||
originalFirDeclaration as FirSimpleFunction,
|
||||
state
|
||||
)
|
||||
is KtProperty -> buildPropertyCopy(
|
||||
is KtProperty -> createPropertyCopy(
|
||||
fakeKtDeclaration,
|
||||
originalFirDeclaration as FirProperty,
|
||||
state
|
||||
)
|
||||
is KtClassOrObject -> createClassCopy(
|
||||
fakeKtDeclaration,
|
||||
originalFirDeclaration as FirRegularClass,
|
||||
state
|
||||
)
|
||||
is KtTypeAlias -> createTypeAliasCopy(
|
||||
fakeKtDeclaration,
|
||||
originalFirDeclaration as FirTypeAlias,
|
||||
state
|
||||
)
|
||||
else -> error("Unsupported declaration ${fakeKtDeclaration::class.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildFunctionCopy(
|
||||
private fun createFunctionCopy(
|
||||
element: KtNamedFunction,
|
||||
originalFunction: FirSimpleFunction,
|
||||
state: FirModuleResolveState,
|
||||
): FirSimpleFunction {
|
||||
val builtFunction = createCopy(element, originalFunction) as FirSimpleFunction
|
||||
val builtFunction = createCopy(element, originalFunction)
|
||||
|
||||
// right now we can't resolve builtFunction header properly, as it built right in air,
|
||||
// without file, which is now required for running stages other then body resolve, so we
|
||||
@@ -57,12 +64,45 @@ object DeclarationCopyBuilder {
|
||||
}.apply { reassignAllReturnTargets(builtFunction) }
|
||||
}
|
||||
|
||||
private fun buildPropertyCopy(
|
||||
private fun createClassCopy(
|
||||
fakeKtClassOrObject: KtClassOrObject,
|
||||
originalFirClass: FirRegularClass,
|
||||
state: FirModuleResolveState,
|
||||
): FirRegularClass {
|
||||
val builtClass = createCopy(fakeKtClassOrObject, originalFirClass)
|
||||
|
||||
return buildRegularClassCopy(originalFirClass) {
|
||||
declarations.clear()
|
||||
declarations.addAll(builtClass.declarations)
|
||||
symbol = builtClass.symbol
|
||||
resolvePhase = minOf(originalFirClass.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||
source = builtClass.source
|
||||
session = state.rootModuleSession
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTypeAliasCopy(
|
||||
fakeKtTypeAlias: KtTypeAlias,
|
||||
originalFirTypeAlias: FirTypeAlias,
|
||||
state: FirModuleResolveState,
|
||||
): FirTypeAlias {
|
||||
val builtTypeAlias = createCopy(fakeKtTypeAlias, originalFirTypeAlias)
|
||||
|
||||
return buildTypeAliasCopy(originalFirTypeAlias) {
|
||||
expandedTypeRef = builtTypeAlias.expandedTypeRef
|
||||
symbol = builtTypeAlias.symbol
|
||||
resolvePhase = minOf(originalFirTypeAlias.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||
source = builtTypeAlias.source
|
||||
session = state.rootModuleSession
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPropertyCopy(
|
||||
element: KtProperty,
|
||||
originalProperty: FirProperty,
|
||||
state: FirModuleResolveState
|
||||
): FirProperty {
|
||||
val builtProperty = createCopy(element, originalProperty) as FirProperty
|
||||
val builtProperty = createCopy(element, originalProperty)
|
||||
|
||||
val originalSetter = originalProperty.setter
|
||||
val builtSetter = builtProperty.setter
|
||||
@@ -80,7 +120,7 @@ object DeclarationCopyBuilder {
|
||||
builtSetter
|
||||
}
|
||||
|
||||
return org.jetbrains.kotlin.fir.declarations.builder.buildPropertyCopy(originalProperty) {
|
||||
return buildPropertyCopy(originalProperty) {
|
||||
symbol = builtProperty.symbol
|
||||
initializer = builtProperty.initializer
|
||||
|
||||
@@ -93,16 +133,16 @@ object DeclarationCopyBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
fun createCopy(
|
||||
internal inline fun <reified T : FirDeclaration> createCopy(
|
||||
fakeKtDeclaration: KtDeclaration,
|
||||
originalFirDeclaration: FirDeclaration,
|
||||
): FirDeclaration {
|
||||
originalFirDeclaration: T,
|
||||
): T {
|
||||
return RawFirFragmentForLazyBodiesBuilder.build(
|
||||
session = originalFirDeclaration.session,
|
||||
baseScopeProvider = originalFirDeclaration.session.firIdeProvider.kotlinScopeProvider,
|
||||
designation = originalFirDeclaration.collectDesignation().fullDesignation,
|
||||
declaration = fakeKtDeclaration
|
||||
)
|
||||
) as T
|
||||
}
|
||||
|
||||
private fun FirFunction<*>.reassignAllReturnTargets(from: FirFunction<*>) {
|
||||
|
||||
+15
-4
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalDeclaration
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
@ThreadSafeMutableState
|
||||
@@ -36,11 +37,21 @@ class FirTowerDataContextCollector {
|
||||
}
|
||||
|
||||
fun FirTowerDataContextCollector.getClosestAvailableParentContext(element: KtElement): FirTowerDataContext? {
|
||||
var current: KtElement = element
|
||||
while (true) {
|
||||
getContext(current)?.let { return it }
|
||||
current = current.parent as? KtElement ?: return null
|
||||
var current: PsiElement? = element
|
||||
while (current != null) {
|
||||
if (current is KtElement) {
|
||||
getContext(current)?.let { return it }
|
||||
}
|
||||
if (current is KtDeclaration) {
|
||||
val originalDeclaration = current.originalDeclaration
|
||||
originalDeclaration?.let { getContext(it) }?.let { return it }
|
||||
}
|
||||
if (current is KtFile) {
|
||||
break
|
||||
}
|
||||
current = current.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private tailrec fun PsiElement.closestBlockLevelOrInitializerExpression(): KtExpression? =
|
||||
|
||||
+2
-2
@@ -80,7 +80,7 @@ internal class ReanalyzableFunctionStructureElement(
|
||||
towerDataContextCollector: FirTowerDataContextCollector,
|
||||
): ReanalyzableFunctionStructureElement {
|
||||
val originalFunction = firSymbol.fir as FirSimpleFunction
|
||||
val newFunction = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalFunction) as FirSimpleFunction
|
||||
val newFunction = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalFunction)
|
||||
|
||||
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalFunction, newFunction) {
|
||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||
@@ -122,7 +122,7 @@ internal class ReanalyzablePropertyStructureElement(
|
||||
towerDataContextCollector: FirTowerDataContextCollector,
|
||||
): ReanalyzablePropertyStructureElement {
|
||||
val originalProperty = firSymbol.fir
|
||||
val newProperty = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalProperty) as FirProperty
|
||||
val newProperty = DeclarationCopyBuilder.createCopy(newKtDeclaration, originalProperty)
|
||||
|
||||
return FileStructureUtil.withDeclarationReplaced(firFile, cache, originalProperty, newProperty) {
|
||||
firLazyDeclarationResolver.lazyResolveDeclaration(
|
||||
|
||||
+6
-6
@@ -34,8 +34,8 @@ internal sealed class EnclosingDeclarationContext {
|
||||
ktDeclaration.canBeEnclosingDeclaration()
|
||||
}
|
||||
if (fakeKtDeclaration != null) {
|
||||
val originalDeclaration = originalFile.findDeclarationOfTypeAt(fakeKtDeclaration.textOffset, fakeKtDeclaration::class)
|
||||
?: error("Cannot find original function matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile")
|
||||
val originalDeclaration = findMatchingElementInCopy(fakeKtDeclaration, originalFile)
|
||||
?: error("Cannot find original declaration matching to ${fakeKtDeclaration.getElementTextInContext()} in $originalFile")
|
||||
recordOriginalDeclaration(originalDeclaration, fakeKtDeclaration)
|
||||
return EnclosingDeclarationContextImpl(fakeKtDeclaration, originalDeclaration)
|
||||
}
|
||||
@@ -62,7 +62,6 @@ internal class EnclosingDeclarationContextImpl(
|
||||
) : EnclosingDeclarationContext()
|
||||
|
||||
|
||||
|
||||
internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile: FirFile, firResolveState: FirModuleResolveState) {
|
||||
LowLevelFirApiFacadeForCompletion.recordCompletionContextForDeclaration(
|
||||
originalFirFile,
|
||||
@@ -73,7 +72,8 @@ internal fun EnclosingDeclarationContext.recordCompletionContext(originalFirFile
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T : KtElement> KtFile.findDeclarationOfTypeAt(offset: Int, declarationType: KClass<T>): T? {
|
||||
val elementAtOffset = findElementAt(offset) ?: return null
|
||||
return PsiTreeUtil.getParentOfType(elementAtOffset, declarationType.java, false)?.takeIf { it.textOffset == offset }
|
||||
fun <T : KtElement> findMatchingElementInCopy(element: T, copy: KtFile): T? {
|
||||
val elementOffset = element.textOffset
|
||||
val elementAtOffset = copy.findElementAt(elementOffset) ?: return null
|
||||
return PsiTreeUtil.getParentOfType(elementAtOffset, element::class.java, false)?.takeIf { it.textOffset == elementOffset }
|
||||
}
|
||||
Reference in New Issue
Block a user